Refactor Repl: use sealed class to represent line result
This commit is contained in:
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.cli.jvm.repl
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.kotlin.cli.common.KotlinVersion
|
||||
import org.jetbrains.kotlin.cli.jvm.repl.LineResult.*
|
||||
import org.jetbrains.kotlin.cli.jvm.repl.messages.unescapeLineBreaks
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import java.io.File
|
||||
@@ -84,8 +85,8 @@ class ReplFromTerminal(
|
||||
return if (notQuit) WhatNextAfterOneLine.READ_LINE else WhatNextAfterOneLine.QUIT
|
||||
}
|
||||
|
||||
val lineResultType = eval(line)
|
||||
if (lineResultType === ReplInterpreter.LineResultType.INCOMPLETE) {
|
||||
val lineResult = eval(line)
|
||||
if (lineResult is LineResult.Incomplete) {
|
||||
return WhatNextAfterOneLine.INCOMPLETE
|
||||
}
|
||||
else {
|
||||
@@ -93,27 +94,20 @@ class ReplFromTerminal(
|
||||
}
|
||||
}
|
||||
|
||||
private fun eval(line: String): ReplInterpreter.LineResultType {
|
||||
private fun eval(line: String): LineResult {
|
||||
val lineResult = replInterpreter.eval(line)
|
||||
if (lineResult.type === ReplInterpreter.LineResultType.SUCCESS) {
|
||||
writer.notifyCommandSuccess()
|
||||
if (!lineResult.isUnit) {
|
||||
writer.outputCommandResult(lineResult.value)
|
||||
when (lineResult) {
|
||||
is ValueResult, UnitResult -> {
|
||||
writer.notifyCommandSuccess()
|
||||
if (lineResult is ValueResult) {
|
||||
writer.outputCommandResult(lineResult.value)
|
||||
}
|
||||
}
|
||||
Incomplete -> writer.notifyIncomplete()
|
||||
is Error.CompileTime -> writer.outputCompileError(lineResult.errorText)
|
||||
is Error.Runtime -> writer.outputRuntimeError(lineResult.errorText)
|
||||
}
|
||||
else if (lineResult.type === ReplInterpreter.LineResultType.INCOMPLETE) {
|
||||
writer.notifyIncomplete()
|
||||
}
|
||||
else if (lineResult.type === ReplInterpreter.LineResultType.COMPILE_ERROR) {
|
||||
writer.outputCompileError(lineResult.errorText!!)
|
||||
}
|
||||
else if (lineResult.type === ReplInterpreter.LineResultType.RUNTIME_ERROR) {
|
||||
writer.outputRuntimeError(lineResult.errorText!!)
|
||||
}
|
||||
else {
|
||||
throw IllegalStateException("unknown line result type: " + lineResult)
|
||||
}
|
||||
return lineResult.type
|
||||
return lineResult
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
|
||||
@@ -70,66 +70,6 @@ class ReplInterpreter(
|
||||
private val psiFileFactory: PsiFileFactoryImpl = PsiFileFactory.getInstance(environment.project) as PsiFileFactoryImpl
|
||||
private val analyzerEngine = CliReplAnalyzerEngine(environment)
|
||||
|
||||
enum class LineResultType {
|
||||
SUCCESS,
|
||||
COMPILE_ERROR,
|
||||
RUNTIME_ERROR,
|
||||
INCOMPLETE
|
||||
}
|
||||
|
||||
class LineResult private constructor(
|
||||
private val resultingValue: Any?,
|
||||
private val unit: Boolean,
|
||||
val errorText: String?,
|
||||
val type: LineResultType
|
||||
) {
|
||||
val value: Any?
|
||||
get() {
|
||||
checkSuccessful()
|
||||
return resultingValue
|
||||
}
|
||||
|
||||
val isUnit: Boolean
|
||||
get() {
|
||||
checkSuccessful()
|
||||
return unit
|
||||
}
|
||||
|
||||
private fun checkSuccessful() {
|
||||
if (type != LineResultType.SUCCESS) {
|
||||
error("it is error")
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun error(errorText: String, errorType: LineResultType): LineResult {
|
||||
val resultingErrorText = when {
|
||||
errorText.isEmpty() -> "<unknown error>"
|
||||
!errorText.endsWith("\n") -> errorText + "\n"
|
||||
else -> errorText
|
||||
}
|
||||
|
||||
return LineResult(null, false, resultingErrorText, errorType)
|
||||
}
|
||||
|
||||
fun successful(value: Any?, unit: Boolean): LineResult {
|
||||
return LineResult(value, unit, null, LineResultType.SUCCESS)
|
||||
}
|
||||
|
||||
fun compileError(errorText: String): LineResult {
|
||||
return error(errorText, LineResultType.COMPILE_ERROR)
|
||||
}
|
||||
|
||||
fun runtimeError(errorText: String): LineResult {
|
||||
return error(errorText, LineResultType.RUNTIME_ERROR)
|
||||
}
|
||||
|
||||
fun incomplete(): LineResult {
|
||||
return LineResult(null, false, null, LineResultType.INCOMPLETE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun eval(line: String): LineResult {
|
||||
++lineNumber
|
||||
|
||||
@@ -149,23 +89,23 @@ class ReplInterpreter(
|
||||
if (syntaxErrorReport.isHasErrors && syntaxErrorReport.isAllErrorsAtEof) {
|
||||
return if (allowIncompleteLines) {
|
||||
previousIncompleteLines.add(line)
|
||||
LineResult.incomplete()
|
||||
LineResult.Incomplete
|
||||
}
|
||||
else {
|
||||
LineResult.compileError(errorHolder.renderedDiagnostics)
|
||||
LineResult.Error.CompileTime(errorHolder.renderedDiagnostics)
|
||||
}
|
||||
}
|
||||
|
||||
previousIncompleteLines.clear()
|
||||
|
||||
if (syntaxErrorReport.isHasErrors) {
|
||||
return LineResult.compileError(errorHolder.renderedDiagnostics)
|
||||
return LineResult.Error.CompileTime(errorHolder.renderedDiagnostics)
|
||||
}
|
||||
|
||||
val analysisResult = analyzerEngine.analyzeReplLine(psiFile, lineNumber)
|
||||
AnalyzerWithCompilerReport.reportDiagnostics(analysisResult.diagnostics, errorHolder, false)
|
||||
val scriptDescriptor = when (analysisResult) {
|
||||
is WithErrors -> return LineResult.compileError(errorHolder.renderedDiagnostics)
|
||||
is WithErrors -> return LineResult.Error.CompileTime(errorHolder.renderedDiagnostics)
|
||||
is Successful -> analysisResult.scriptDescriptor
|
||||
else -> error("Unexpected result ${analysisResult.javaClass}")
|
||||
}
|
||||
@@ -196,7 +136,7 @@ class ReplInterpreter(
|
||||
scriptInstanceConstructor.newInstance(*constructorArgs)
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
return LineResult.runtimeError(renderStackTrace(e.cause!!))
|
||||
return LineResult.Error.Runtime(renderStackTrace(e.cause!!))
|
||||
}
|
||||
finally {
|
||||
onUserCodeExecuting(false)
|
||||
@@ -207,7 +147,10 @@ class ReplInterpreter(
|
||||
|
||||
earlierLines.add(EarlierLine(line, scriptDescriptor, scriptClass, scriptInstance))
|
||||
|
||||
return LineResult.successful(rv, !state.replSpecific.hasResult)
|
||||
if (!state.replSpecific.hasResult) {
|
||||
return LineResult.UnitResult
|
||||
}
|
||||
return LineResult.ValueResult(rv)
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
val writer = PrintWriter(System.err)
|
||||
@@ -275,3 +218,15 @@ class ReplInterpreter(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed class LineResult {
|
||||
class ValueResult(val value: Any?): LineResult()
|
||||
|
||||
object UnitResult: LineResult()
|
||||
object Incomplete : LineResult()
|
||||
|
||||
sealed class Error(val errorText: String): LineResult() {
|
||||
class Runtime(errorText: String): Error(errorText)
|
||||
class CompileTime(errorText: String): Error(errorText)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user