Implement support for "resX" result fields in REPL
This commit is contained in:
committed by
Ilya Chernikov
parent
79e577ae27
commit
c901d6cebc
+3
-7
@@ -108,18 +108,14 @@ open class GenericReplEvaluator(
|
||||
|
||||
historyActor.addFinal(compileResult.lineId, EvalClassWithInstanceAndLoader(scriptClass.kotlin, scriptInstance, classLoader, invokeWrapper))
|
||||
|
||||
val resultField = scriptClass.getDeclaredField(SCRIPT_RESULT_FIELD_NAME).apply { isAccessible = true }
|
||||
val resultFieldName = scriptResultFieldName(compileResult.lineId.no)
|
||||
val resultField = scriptClass.getDeclaredField(resultFieldName).apply { isAccessible = true }
|
||||
val resultValue: Any? = resultField.get(scriptInstance)
|
||||
|
||||
return if (compileResult.hasResult) ReplEvalResult.ValueResult(resultValue, compileResult.type)
|
||||
return if (compileResult.hasResult) ReplEvalResult.ValueResult(resultFieldName, resultValue, compileResult.type)
|
||||
else ReplEvalResult.UnitResult()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val SCRIPT_RESULT_FIELD_NAME = "\$\$result"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private open class HistoryActionsForNoRepeat(val state: GenericReplEvaluatorState) {
|
||||
|
||||
@@ -121,8 +121,11 @@ interface ReplEvalAction {
|
||||
}
|
||||
|
||||
sealed class ReplEvalResult : Serializable {
|
||||
class ValueResult(val value: Any?, val type: String?) : ReplEvalResult() {
|
||||
override fun toString(): String = "$value : $type"
|
||||
class ValueResult(val name: String, val value: Any?, val type: String?) : ReplEvalResult() {
|
||||
override fun toString(): String {
|
||||
return "$name: $type = $value"
|
||||
}
|
||||
|
||||
companion object { private val serialVersionUID: Long = 1L }
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,8 @@ fun String.replNormalizeLineBreaks() = replace(END_LINE, "\n")
|
||||
fun makeScriptBaseName(codeLine: ReplCodeLine) =
|
||||
"Line_${codeLine.no}${if (codeLine.generation > REPL_CODE_LINE_FIRST_GEN) "_gen_${codeLine.generation}" else ""}"
|
||||
|
||||
fun scriptResultFieldName(lineNo: Int) = "res$lineNo"
|
||||
|
||||
fun renderReplStackTrace(cause: Throwable, startFromMethodName: String): String {
|
||||
val newTrace = arrayListOf<StackTraceElement>()
|
||||
var skip = true
|
||||
|
||||
@@ -27,12 +27,8 @@ import org.jetbrains.kotlin.codegen.CompilationErrorHandler
|
||||
import org.jetbrains.kotlin.codegen.KotlinCodegenFacade
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtScript
|
||||
import org.jetbrains.kotlin.psi.KtScriptInitializer
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||
import org.jetbrains.kotlin.script.ScriptDependenciesProvider
|
||||
import java.io.File
|
||||
@@ -92,6 +88,8 @@ open class GenericReplCompiler(
|
||||
else -> error("Unexpected result ${analysisResult::class.java}")
|
||||
}
|
||||
|
||||
val type = (scriptDescriptor as LazyScriptDescriptor).resultValue?.returnType
|
||||
|
||||
val generationState = GenerationState.Builder(
|
||||
psiFile.project,
|
||||
ClassBuilderFactories.BINARIES,
|
||||
@@ -100,7 +98,9 @@ open class GenericReplCompiler(
|
||||
listOf(psiFile),
|
||||
compilerConfiguration
|
||||
).build()
|
||||
generationState.replSpecific.scriptResultFieldName = SCRIPT_RESULT_FIELD_NAME
|
||||
|
||||
generationState.replSpecific.resultType = type
|
||||
generationState.replSpecific.scriptResultFieldName = scriptResultFieldName(codeLine.no)
|
||||
generationState.replSpecific.earlierScriptsForReplInterpreter = compilerState.history.map { it.item }
|
||||
generationState.beforeCompile()
|
||||
KotlinCodegenFacade.generatePackage(
|
||||
@@ -113,23 +113,18 @@ open class GenericReplCompiler(
|
||||
val generatedClassname = makeScriptBaseName(codeLine)
|
||||
compilerState.history.push(LineId(codeLine), scriptDescriptor)
|
||||
|
||||
val expression = psiFile.getChildOfType<KtScript>()?.getChildOfType<KtBlockExpression>()?.getChildOfType<KtScriptInitializer>()
|
||||
?.getChildOfType<KtExpression>()
|
||||
|
||||
val type = expression?.let {
|
||||
compilerState.analyzerEngine.trace.bindingContext.getType(it)
|
||||
}?.let {
|
||||
DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(it)
|
||||
}
|
||||
val classes = generationState.factory.asList().map { CompiledClassData(it.relativePath, it.asByteArray()) }
|
||||
|
||||
return ReplCompileResult.CompiledClasses(
|
||||
LineId(codeLine),
|
||||
compilerState.history.map { it.id },
|
||||
generatedClassname,
|
||||
generationState.factory.asList().map { CompiledClassData(it.relativePath, it.asByteArray()) },
|
||||
classes,
|
||||
generationState.replSpecific.hasResult,
|
||||
classpathAddendum ?: emptyList(),
|
||||
type
|
||||
generationState.replSpecific.resultType?.let {
|
||||
DescriptorRenderer.FQ_NAMES_IN_TYPES.renderType(it)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ class ReplFromTerminal(
|
||||
is ReplEvalResult.ValueResult, is ReplEvalResult.UnitResult -> {
|
||||
writer.notifyCommandSuccess()
|
||||
if (evalResult is ReplEvalResult.ValueResult) {
|
||||
writer.outputCommandResult(evalResult.value.toString())
|
||||
writer.outputCommandResult(evalResult.toString())
|
||||
}
|
||||
}
|
||||
is ReplEvalResult.Error.Runtime -> writer.outputRuntimeError(evalResult.message)
|
||||
|
||||
Reference in New Issue
Block a user