J2K ReplInterpreter: prettify

This commit is contained in:
Alexander Udalov
2016-02-03 14:07:27 +05:30
committed by Alexander Udalov
parent 5670e7f750
commit 2e13377d4a
2 changed files with 106 additions and 158 deletions
@@ -17,27 +17,23 @@
package org.jetbrains.kotlin.cli.jvm.repl package org.jetbrains.kotlin.cli.jvm.repl
import com.google.common.base.Throwables import com.google.common.base.Throwables
import com.google.common.collect.Lists
import com.intellij.openapi.Disposable import com.intellij.openapi.Disposable
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.CharsetToolkit import com.intellij.openapi.vfs.CharsetToolkit
import com.intellij.psi.PsiFile import com.intellij.psi.PsiFile
import com.intellij.psi.PsiFileFactory import com.intellij.psi.PsiFileFactory
import com.intellij.psi.impl.PsiFileFactoryImpl import com.intellij.psi.impl.PsiFileFactoryImpl
import com.intellij.psi.search.ProjectScope import com.intellij.psi.search.ProjectScope
import com.intellij.testFramework.LightVirtualFile import com.intellij.testFramework.LightVirtualFile
import org.jetbrains.kotlin.backend.common.output.OutputFile
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.common.messages.DiagnosticMessageReporter import org.jetbrains.kotlin.cli.common.messages.DiagnosticMessageReporter
import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.config.* import org.jetbrains.kotlin.cli.jvm.config.getModuleName
import org.jetbrains.kotlin.cli.jvm.config.* import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
import org.jetbrains.kotlin.cli.jvm.repl.di.ContainerForReplWithJava
import org.jetbrains.kotlin.cli.jvm.repl.di.*
import org.jetbrains.kotlin.cli.jvm.repl.di.ReplLastLineScopeProvider import org.jetbrains.kotlin.cli.jvm.repl.di.ReplLastLineScopeProvider
import org.jetbrains.kotlin.cli.jvm.repl.di.createContainerForReplWithJava
import org.jetbrains.kotlin.cli.jvm.repl.messages.DiagnosticMessageHolder import org.jetbrains.kotlin.cli.jvm.repl.messages.DiagnosticMessageHolder
import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplIdeDiagnosticMessageHolder import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplIdeDiagnosticMessageHolder
import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplSystemInWrapper import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplSystemInWrapper
@@ -48,7 +44,6 @@ import org.jetbrains.kotlin.codegen.KotlinCodegenFacade
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.context.MutableModuleContext
import org.jetbrains.kotlin.descriptors.ScriptDescriptor import org.jetbrains.kotlin.descriptors.ScriptDescriptor
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
@@ -65,33 +60,25 @@ import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM
import org.jetbrains.kotlin.resolve.lazy.ResolveSession import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import org.jetbrains.kotlin.resolve.lazy.data.KtClassLikeInfo import org.jetbrains.kotlin.resolve.lazy.data.KtClassLikeInfo
import org.jetbrains.kotlin.resolve.lazy.declarations.* import org.jetbrains.kotlin.resolve.lazy.declarations.*
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor
import org.jetbrains.kotlin.resolve.scopes.LexicalScope import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.script.* import org.jetbrains.kotlin.script.KotlinScriptDefinition
import org.jetbrains.kotlin.utils.* import org.jetbrains.kotlin.script.ScriptParameter
import org.jetbrains.kotlin.script.ScriptPriorities
import java.io.File import org.jetbrains.kotlin.script.StandardScriptDefinition
import java.io.PrintWriter import java.io.PrintWriter
import java.lang.reflect.Constructor
import java.lang.reflect.Field
import java.net.MalformedURLException
import java.net.URL
import java.net.URLClassLoader import java.net.URLClassLoader
import java.util.ArrayList
import java.util.Arrays
import java.util.Collections
class ReplInterpreter( class ReplInterpreter(
disposable: Disposable, disposable: Disposable,
configuration: CompilerConfiguration, configuration: CompilerConfiguration,
private val ideMode: Boolean, private val ideMode: Boolean,
private val replReader: ReplSystemInWrapper?) { private val replReader: ReplSystemInWrapper?
) {
private var lineNumber = 0 private var lineNumber = 0
private var lastLineScope: LexicalScope? = null private var lastLineScope: LexicalScope? = null
private val earlierLines = Lists.newArrayList<EarlierLine>() private val earlierLines = arrayListOf<EarlierLine>()
private val previousIncompleteLines = Lists.newArrayList<String>() private val previousIncompleteLines = arrayListOf<String>()
private val classLoader: ReplClassLoader private val classLoader: ReplClassLoader
private val psiFileFactory: PsiFileFactoryImpl private val psiFileFactory: PsiFileFactoryImpl
@@ -123,32 +110,27 @@ class ReplInterpreter(
ProjectScope.getAllScope(project), ProjectScope.getAllScope(project),
object : ReplLastLineScopeProvider { object : ReplLastLineScopeProvider {
override val lastLineScope: LexicalScope? override val lastLineScope: LexicalScope?
get() = lastLineScope get() = this@ReplInterpreter.lastLineScope
}, },
JvmPackagePartProvider(environment)) JvmPackagePartProvider(environment)
)
this.topDownAnalysisContext = TopDownAnalysisContext(TopDownAnalysisMode.LocalDeclarations, DataFlowInfoFactory.EMPTY, this.topDownAnalysisContext = TopDownAnalysisContext(
container.resolveSession.declarationScopeProvider) TopDownAnalysisMode.LocalDeclarations, DataFlowInfoFactory.EMPTY, container.resolveSession.declarationScopeProvider
)
this.topDownAnalyzer = container.lazyTopDownAnalyzerForTopLevel this.topDownAnalyzer = container.lazyTopDownAnalyzerForTopLevel
this.resolveSession = container.resolveSession this.resolveSession = container.resolveSession
moduleContext.initializeModuleContents(CompositePackageFragmentProvider( moduleContext.initializeModuleContents(CompositePackageFragmentProvider(
Arrays.asList( listOf(
container.resolveSession.packageFragmentProvider, container.resolveSession.packageFragmentProvider,
container.javaDescriptorResolver.packageFragmentProvider))) container.javaDescriptorResolver.packageFragmentProvider
)
))
val classpath = Lists.newArrayList<URL>() val classpath = configuration.jvmClasspathRoots.map { it.toURI().toURL() }
for (file in configuration.jvmClasspathRoots) {
try {
classpath.add(file.toURI().toURL())
}
catch (e: MalformedURLException) {
throw rethrow(e)
}
} this.classLoader = ReplClassLoader(URLClassLoader(classpath.toTypedArray(), null))
this.classLoader = ReplClassLoader(URLClassLoader(classpath.toArray<URL>(arrayOfNulls<URL>(classpath.size)), null))
} }
enum class LineResultType { enum class LineResultType {
@@ -158,18 +140,17 @@ class ReplInterpreter(
INCOMPLETE INCOMPLETE
} }
class LineResult private constructor(private val value: Any?, private val unit: Boolean, val errorText: String?, val type: LineResultType) { class LineResult private constructor(
private val resultingValue: Any?,
private fun checkSuccessful() { private val unit: Boolean,
if (type != LineResultType.SUCCESS) { val errorText: String?,
throw IllegalStateException("it is error") val type: LineResultType
) {
val value: Any?
get() {
checkSuccessful()
return resultingValue
} }
}
fun getValue(): Any? {
checkSuccessful()
return value
}
val isUnit: Boolean val isUnit: Boolean
get() { get() {
@@ -177,21 +158,24 @@ class ReplInterpreter(
return unit return unit
} }
private fun checkSuccessful() {
if (type != LineResultType.SUCCESS) {
error("it is error")
}
}
companion object { companion object {
private fun error(errorText: String, errorType: LineResultType): LineResult { private fun error(errorText: String, errorType: LineResultType): LineResult {
var errorText = errorText val resultingErrorText = when {
if (errorText.isEmpty()) { errorText.isEmpty() -> "<unknown error>"
errorText = "<unknown error>" !errorText.endsWith("\n") -> errorText + "\n"
} else -> errorText
else if (!errorText.endsWith("\n")) {
errorText += "\n"
} }
return LineResult(null, false, errorText, errorType) return LineResult(null, false, resultingErrorText, errorType)
} }
fun successful(value: Any, unit: Boolean): LineResult { fun successful(value: Any?, unit: Boolean): LineResult {
return LineResult(value, unit, null, LineResultType.SUCCESS) return LineResult(value, unit, null, LineResultType.SUCCESS)
} }
@@ -209,39 +193,35 @@ class ReplInterpreter(
} }
} }
private fun createDiagnosticHolder(): DiagnosticMessageHolder { private fun createDiagnosticHolder(): DiagnosticMessageHolder =
return if (ideMode) if (ideMode)
ReplIdeDiagnosticMessageHolder() ReplIdeDiagnosticMessageHolder()
else else
ReplTerminalDiagnosticMessageHolder() ReplTerminalDiagnosticMessageHolder()
}
fun eval(line: String): LineResult { fun eval(line: String): LineResult {
++lineNumber ++lineNumber
val scriptFqName = FqName("Line" + lineNumber) val fullText = (previousIncompleteLines + line).joinToString(separator = "\n")
val fullText = StringBuilder() val virtualFile =
for (prevLine in previousIncompleteLines) { LightVirtualFile("line$lineNumber${KotlinParserDefinition.STD_SCRIPT_EXT}", KotlinLanguage.INSTANCE, fullText).apply {
fullText.append(prevLine).append("\n") charset = CharsetToolkit.UTF8_CHARSET
} }
fullText.append(line) val psiFile = psiFileFactory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, true, false) as KtFile?
?: error("Script file not analyzed at line $lineNumber: $fullText")
val virtualFile = LightVirtualFile("line" + lineNumber + KotlinParserDefinition.STD_SCRIPT_EXT, KotlinLanguage.INSTANCE, fullText.toString())
virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET)
val psiFile = psiFileFactory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, true, false) as KtFile? ?: error("Script file not analyzed at line $lineNumber: $fullText")
val errorHolder = createDiagnosticHolder() val errorHolder = createDiagnosticHolder()
val syntaxErrorReport = AnalyzerWithCompilerReport.reportSyntaxErrors(psiFile, errorHolder) val syntaxErrorReport = AnalyzerWithCompilerReport.reportSyntaxErrors(psiFile, errorHolder)
if (syntaxErrorReport.isHasErrors && syntaxErrorReport.isAllErrorsAtEof) { if (syntaxErrorReport.isHasErrors && syntaxErrorReport.isAllErrorsAtEof) {
if (ideMode) { return if (ideMode) {
return LineResult.compileError(errorHolder.renderedDiagnostics) LineResult.compileError(errorHolder.renderedDiagnostics)
} }
else { else {
previousIncompleteLines.add(line) previousIncompleteLines.add(line)
return LineResult.incomplete() LineResult.incomplete()
} }
} }
@@ -254,21 +234,14 @@ class ReplInterpreter(
prepareForTheNextReplLine(topDownAnalysisContext) prepareForTheNextReplLine(topDownAnalysisContext)
trace.clearDiagnostics() trace.clearDiagnostics()
//noinspection ConstantConditions psiFile.script!!.putUserData(ScriptPriorities.PRIORITY_KEY, lineNumber)
psiFile!!.script!!.putUserData(ScriptPriorities.PRIORITY_KEY, lineNumber)
val scriptDescriptor = doAnalyze(psiFile, errorHolder) ?: return LineResult.compileError(errorHolder.renderedDiagnostics) val scriptDescriptor = doAnalyze(psiFile, errorHolder)
?: return LineResult.compileError(errorHolder.renderedDiagnostics)
val earlierScripts = Lists.newArrayList<ScriptDescriptor>() val state = GenerationState(psiFile.project, ClassBuilderFactories.BINARIES, module, trace.bindingContext, listOf(psiFile))
for (earlierLine in earlierLines) { compileScript(psiFile.script!!, earlierLines.map(EarlierLine::getScriptDescriptor), state, CompilationErrorHandler.THROW_EXCEPTION)
earlierScripts.add(earlierLine.scriptDescriptor)
}
val state = GenerationState(psiFile.project, ClassBuilderFactories.BINARIES,
module, trace.bindingContext, listOf(psiFile))
compileScript(psiFile.script!!, earlierScripts, state, CompilationErrorHandler.THROW_EXCEPTION)
for (outputFile in state.factory.asList()) { for (outputFile in state.factory.asList()) {
if (outputFile.relativePath.endsWith(".class")) { if (outputFile.relativePath.endsWith(".class")) {
@@ -278,31 +251,24 @@ class ReplInterpreter(
} }
try { try {
val scriptClass = classLoader.loadClass(scriptFqName.asString()) val scriptClass = classLoader.loadClass("Line$lineNumber")
val constructorParams = arrayOfNulls<Class<*>>(earlierLines.size) val constructorParams = earlierLines.map(EarlierLine::getScriptClass).toTypedArray()
val constructorArgs = arrayOfNulls<Any>(earlierLines.size) val constructorArgs = earlierLines.map(EarlierLine::getScriptInstance).toTypedArray()
for (i in earlierLines.indices) {
constructorParams[i] = earlierLines[i].scriptClass
constructorArgs[i] = earlierLines[i].scriptInstance
}
val scriptInstanceConstructor = scriptClass.getConstructor(*constructorParams) val scriptInstanceConstructor = scriptClass.getConstructor(*constructorParams)
val scriptInstance: Any val scriptInstance = try {
try { replReader?.isReplScriptExecuting = true
setReplScriptExecuting(true) scriptInstanceConstructor.newInstance(*constructorArgs)
scriptInstance = scriptInstanceConstructor.newInstance(*constructorArgs)
} }
catch (e: Throwable) { catch (e: Throwable) {
return LineResult.runtimeError(renderStackTrace(e.cause!!)) return LineResult.runtimeError(renderStackTrace(e.cause!!))
} }
finally { finally {
setReplScriptExecuting(false) replReader?.isReplScriptExecuting = false
} }
val rvField = scriptClass.getDeclaredField(SCRIPT_RESULT_FIELD_NAME) val rvField = scriptClass.getDeclaredField(SCRIPT_RESULT_FIELD_NAME).apply { isAccessible = true }
rvField.isAccessible = true
val rv = rvField.get(scriptInstance) val rv = rvField.get(scriptInstance)
earlierLines.add(EarlierLine(line, scriptDescriptor, scriptClass, scriptInstance)) earlierLines.add(EarlierLine(line, scriptDescriptor, scriptClass, scriptInstance))
@@ -310,28 +276,17 @@ class ReplInterpreter(
return LineResult.successful(rv, !state.replSpecific.hasResult) return LineResult.successful(rv, !state.replSpecific.hasResult)
} }
catch (e: Throwable) { catch (e: Throwable) {
@SuppressWarnings("UseOfSystemOutOrSystemErr")
val writer = PrintWriter(System.err) val writer = PrintWriter(System.err)
classLoader.dumpClasses(writer) classLoader.dumpClasses(writer)
writer.flush() writer.flush()
throw rethrow(e) throw e
}
}
private fun setReplScriptExecuting(isExecuting: Boolean) {
if (replReader != null) {
replReader.isReplScriptExecuting = isExecuting
} }
} }
private fun doAnalyze(psiFile: KtFile, errorReporter: DiagnosticMessageReporter): ScriptDescriptor? { private fun doAnalyze(psiFile: KtFile, errorReporter: DiagnosticMessageReporter): ScriptDescriptor? {
scriptDeclarationFactory.setDelegateFactory( scriptDeclarationFactory.setDelegateFactory(FileBasedDeclarationProviderFactory(resolveSession.storageManager, listOf(psiFile)))
FileBasedDeclarationProviderFactory(resolveSession.storageManager, listOf(psiFile)))
val context = topDownAnalyzer.analyzeDeclarations( val context = topDownAnalyzer.analyzeDeclarations(topDownAnalysisContext.topDownAnalysisMode, listOf(psiFile))
topDownAnalysisContext.topDownAnalysisMode,
listOf(psiFile))
if (trace.get(BindingContext.FILE_TO_PACKAGE_FRAGMENT, psiFile) == null) { if (trace.get(BindingContext.FILE_TO_PACKAGE_FRAGMENT, psiFile) == null) {
trace.record(BindingContext.FILE_TO_PACKAGE_FRAGMENT, psiFile, resolveSession.getPackageFragment(FqName.ROOT)) trace.record(BindingContext.FILE_TO_PACKAGE_FRAGMENT, psiFile, resolveSession.getPackageFragment(FqName.ROOT))
@@ -342,9 +297,9 @@ class ReplInterpreter(
return null return null
} }
val scriptDescriptor = context.scripts[psiFile.script]!! return context.scripts[psiFile.script]?.apply {
lastLineScope = scriptDescriptor.getScopeForInitializerResolution() lastLineScope = this.scopeForInitializerResolution
return scriptDescriptor }
} }
fun dumpClasses(out: PrintWriter) { fun dumpClasses(out: PrintWriter) {
@@ -352,23 +307,23 @@ class ReplInterpreter(
} }
private class ScriptMutableDeclarationProviderFactory : DeclarationProviderFactory { private class ScriptMutableDeclarationProviderFactory : DeclarationProviderFactory {
private var delegateFactory: DeclarationProviderFactory? = null private lateinit var delegateFactory: DeclarationProviderFactory
private var rootPackageProvider: AdaptablePackageMemberDeclarationProvider? = null private lateinit var rootPackageProvider: AdaptablePackageMemberDeclarationProvider
fun setDelegateFactory(delegateFactory: DeclarationProviderFactory) { fun setDelegateFactory(delegateFactory: DeclarationProviderFactory) {
this.delegateFactory = delegateFactory this.delegateFactory = delegateFactory
val provider = delegateFactory.getPackageMemberDeclarationProvider(FqName.ROOT)!! val provider = delegateFactory.getPackageMemberDeclarationProvider(FqName.ROOT)!!
if (rootPackageProvider == null) { try {
rootPackageProvider = AdaptablePackageMemberDeclarationProvider(provider) rootPackageProvider.addDelegateProvider(provider)
} }
else { catch (e: UninitializedPropertyAccessException) {
rootPackageProvider!!.addDelegateProvider(provider) rootPackageProvider = AdaptablePackageMemberDeclarationProvider(provider)
} }
} }
override fun getClassMemberDeclarationProvider(classLikeInfo: KtClassLikeInfo): ClassMemberDeclarationProvider { override fun getClassMemberDeclarationProvider(classLikeInfo: KtClassLikeInfo): ClassMemberDeclarationProvider {
return delegateFactory!!.getClassMemberDeclarationProvider(classLikeInfo) return delegateFactory.getClassMemberDeclarationProvider(classLikeInfo)
} }
override fun getPackageMemberDeclarationProvider(packageFqName: FqName): PackageMemberDeclarationProvider? { override fun getPackageMemberDeclarationProvider(packageFqName: FqName): PackageMemberDeclarationProvider? {
@@ -376,17 +331,18 @@ class ReplInterpreter(
return rootPackageProvider return rootPackageProvider
} }
return this.delegateFactory!!.getPackageMemberDeclarationProvider(packageFqName) return delegateFactory.getPackageMemberDeclarationProvider(packageFqName)
} }
override fun diagnoseMissingPackageFragment(file: KtFile) { override fun diagnoseMissingPackageFragment(file: KtFile) {
this.delegateFactory!!.diagnoseMissingPackageFragment(file) delegateFactory.diagnoseMissingPackageFragment(file)
} }
class AdaptablePackageMemberDeclarationProvider(private var delegateProvider: PackageMemberDeclarationProvider) : DelegatePackageMemberDeclarationProvider(delegateProvider) { class AdaptablePackageMemberDeclarationProvider(
private var delegateProvider: PackageMemberDeclarationProvider
) : DelegatePackageMemberDeclarationProvider(delegateProvider) {
fun addDelegateProvider(provider: PackageMemberDeclarationProvider) { fun addDelegateProvider(provider: PackageMemberDeclarationProvider) {
delegateProvider = CombinedPackageMemberDeclarationProvider(Lists.newArrayList(provider, delegateProvider)) delegateProvider = CombinedPackageMemberDeclarationProvider(listOf(provider, delegateProvider))
delegate = delegateProvider delegate = delegateProvider
} }
@@ -396,17 +352,11 @@ class ReplInterpreter(
companion object { companion object {
private val SCRIPT_RESULT_FIELD_NAME = "\$\$result" private val SCRIPT_RESULT_FIELD_NAME = "\$\$result"
private val REPL_LINE_AS_SCRIPT_DEFINITION = object : KotlinScriptDefinition { private val REPL_LINE_AS_SCRIPT_DEFINITION = object : KotlinScriptDefinition {
override fun getScriptParameters(scriptDescriptor: ScriptDescriptor): List<ScriptParameter> { override fun getScriptParameters(scriptDescriptor: ScriptDescriptor): List<ScriptParameter> = emptyList()
return emptyList()
}
override fun isScript(file: PsiFile): Boolean { override fun isScript(file: PsiFile): Boolean = StandardScriptDefinition.isScript(file)
return StandardScriptDefinition.isScript(file)
}
override fun getScriptName(script: KtScript): Name { override fun getScriptName(script: KtScript): Name = StandardScriptDefinition.getScriptName(script)
return StandardScriptDefinition.getScriptName(script)
}
} }
private fun prepareForTheNextReplLine(c: TopDownAnalysisContext) { private fun prepareForTheNextReplLine(c: TopDownAnalysisContext) {
@@ -414,26 +364,23 @@ class ReplInterpreter(
} }
private fun renderStackTrace(cause: Throwable): String { private fun renderStackTrace(cause: Throwable): String {
val oldTrace = cause.stackTrace val newTrace = arrayListOf<StackTraceElement>()
val newTrace = ArrayList<StackTraceElement>()
var skip = true var skip = true
for (i in oldTrace.indices.reversed()) { for ((i, element) in cause.stackTrace.withIndex().reversed()) {
val element = oldTrace[i]
// All our code happens in the script constructor, and no reflection/native code happens in constructors. // All our code happens in the script constructor, and no reflection/native code happens in constructors.
// So we ignore everything in the stack trace until the first constructor // So we ignore everything in the stack trace until the first constructor
if (element.getMethodName() == "<init>") { if (element.methodName == "<init>") {
skip = false skip = false
} }
if (!skip) { if (!skip) {
newTrace.add(element) newTrace.add(element)
} }
} }
Collections.reverse(newTrace)
// throw away last element which contains Line1.kts<init>(Unknown source) // throw away last element which contains Line1.kts<init>(Unknown source)
val resultingTrace = newTrace.subList(0, newTrace.size - 1) val resultingTrace = newTrace.reversed().dropLast(1)
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UsePropertyAccessSyntax")
(cause as java.lang.Throwable).setStackTrace(resultingTrace.toTypedArray()) (cause as java.lang.Throwable).setStackTrace(resultingTrace.toTypedArray())
return Throwables.getStackTraceAsString(cause) return Throwables.getStackTraceAsString(cause)
@@ -443,16 +390,18 @@ class ReplInterpreter(
script: KtScript, script: KtScript,
earlierScripts: List<ScriptDescriptor>, earlierScripts: List<ScriptDescriptor>,
state: GenerationState, state: GenerationState,
errorHandler: CompilationErrorHandler) { errorHandler: CompilationErrorHandler
) {
state.replSpecific.scriptResultFieldName = SCRIPT_RESULT_FIELD_NAME state.replSpecific.scriptResultFieldName = SCRIPT_RESULT_FIELD_NAME
state.replSpecific.earlierScriptsForReplInterpreter = ArrayList(earlierScripts) state.replSpecific.earlierScriptsForReplInterpreter = earlierScripts.toList()
state.beforeCompile() state.beforeCompile()
KotlinCodegenFacade.generatePackage( KotlinCodegenFacade.generatePackage(
state, state,
script.getContainingKtFile().packageFqName, script.getContainingKtFile().packageFqName,
setOf(script.getContainingKtFile()), setOf(script.getContainingKtFile()),
errorHandler) errorHandler
)
} }
} }
} }
@@ -27,7 +27,6 @@ import java.io.File
import java.io.PrintWriter import java.io.PrintWriter
import java.util.* import java.util.*
import java.util.regex.Pattern import java.util.regex.Pattern
import kotlin.text.Regex
// Switch this flag to render bytecode after each line in the REPL test. Useful for debugging verify errors or other codegen problems // Switch this flag to render bytecode after each line in the REPL test. Useful for debugging verify errors or other codegen problems
private val DUMP_BYTECODE = false private val DUMP_BYTECODE = false
@@ -94,7 +93,7 @@ abstract class AbstractReplInterpreterTest : UsefulTestCase() {
val actual = when (lineResult.type) { val actual = when (lineResult.type) {
ReplInterpreter.LineResultType.SUCCESS -> if (!lineResult.isUnit) "${lineResult.value}" else "" ReplInterpreter.LineResultType.SUCCESS -> if (!lineResult.isUnit) "${lineResult.value}" else ""
ReplInterpreter.LineResultType.RUNTIME_ERROR, ReplInterpreter.LineResultType.RUNTIME_ERROR,
ReplInterpreter.LineResultType.COMPILE_ERROR -> lineResult.errorText ReplInterpreter.LineResultType.COMPILE_ERROR -> lineResult.errorText!!
ReplInterpreter.LineResultType.INCOMPLETE -> INCOMPLETE_LINE_MESSAGE ReplInterpreter.LineResultType.INCOMPLETE -> INCOMPLETE_LINE_MESSAGE
} }