Skip to content

Commit 946173b

Browse files
committedApr 13, 2020
Switch to a new REPL API
1 parent 2a78703 commit 946173b

File tree

6 files changed

+49
-37
lines changed

6 files changed

+49
-37
lines changed
 

‎src/main/kotlin/org/jetbrains/kotlin/jupyter/repl.kt

+10-12
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package org.jetbrains.kotlin.jupyter
33
import jupyter.kotlin.*
44
import jupyter.kotlin.KotlinContext
55
import jupyter.kotlin.KotlinReceiver
6+
import kotlinx.coroutines.runBlocking
67
import org.jetbrains.kotlin.config.KotlinCompilerVersion
78
import org.jetbrains.kotlin.jupyter.repl.completion.CompletionResult
89
import org.jetbrains.kotlin.jupyter.repl.completion.KotlinCompleter
@@ -11,17 +12,14 @@ import org.jetbrains.kotlin.jupyter.repl.completion.SourceCodeImpl
1112
import org.jetbrains.kotlin.jupyter.repl.reflect.ContextUpdater
1213
import org.jetbrains.kotlin.jupyter.repl.spark.ClassWriter
1314
import org.jetbrains.kotlin.scripting.ide_services.compiler.KJvmReplCompilerImpl
14-
import org.jetbrains.kotlin.scripting.ide_services.evaluator.KJvmReplEvaluatorImpl
1515
import java.io.File
1616
import java.net.URLClassLoader
1717
import java.util.*
1818
import kotlin.script.dependencies.ScriptContents
1919
import kotlin.script.experimental.api.*
2020
import kotlin.script.experimental.host.withDefaultsFrom
2121
import kotlin.script.experimental.jvm.*
22-
import kotlin.script.experimental.util.hasErrors
23-
import kotlin.script.experimental.util.isIncomplete
24-
import kotlin.script.experimental.util.renderError
22+
import kotlin.script.experimental.util.*
2523

2624
data class EvalResult(val resultValue: Any?)
2725

@@ -264,7 +262,7 @@ class ReplForJupyterImpl(val scriptClasspath: List<File> = emptyList(),
264262

265263
override fun checkComplete(executionNumber: Long, code: String): CheckResult {
266264
val codeLine = SourceCodeImpl(executionNumber.toInt(), code)
267-
val result = compiler.analyze(codeLine, 0, compilerConfiguration)
265+
val result = runBlocking { compiler.analyze(codeLine, 0.toSourceCodePosition(codeLine), compilerConfiguration) }
268266
return when {
269267
result.isIncomplete() -> CheckResult(false)
270268
result.hasErrors() -> throw ReplException(result.renderError())
@@ -322,7 +320,7 @@ class ReplForJupyterImpl(val scriptClasspath: List<File> = emptyList(),
322320
typeRenderers.putAll(p.typeRenderers.map { it.className to it.code })
323321
}
324322

325-
private fun lastReplLine() = evaluator.lastEvaluatedSnippet()?.snippetObject
323+
private fun lastReplLine() = evaluator.lastEvaluatedSnippet?.get()?.snippetClass
326324

327325
override fun eval(code: String, displayHandler: ((Any) -> Unit)?, jupyterId: Int): EvalResult {
328326
synchronized(this) {
@@ -413,7 +411,7 @@ class ReplForJupyterImpl(val scriptClasspath: List<File> = emptyList(),
413411
override suspend fun listErrors(code: String, callback: (ListErrorsResult) -> Unit) = doWithLock(ListErrorsArgs(code, callback), listErrorsQueue, ListErrorsResult(code)) {
414412
//val preprocessed = preprocessCode(code)
415413
val codeLine = SourceCodeImpl(executionCounter++, code)
416-
val errorsList = compiler.analyze(codeLine, 0, compilerConfiguration)
414+
val errorsList = runBlocking { compiler.analyze(codeLine, 0.toSourceCodePosition(codeLine), compilerConfiguration) }
417415
ListErrorsResult(code, errorsList.valueOrThrow())
418416
}
419417

@@ -463,25 +461,25 @@ class ReplForJupyterImpl(val scriptClasspath: List<File> = emptyList(),
463461
println(code)
464462
val id = executionCounter++
465463
val codeLine = SourceCodeImpl(id, code)
466-
when (val compileResultWithDiagnostics = compiler.compile(codeLine, compilerConfiguration)) {
464+
when (val compileResultWithDiagnostics = runBlocking { compiler.compile(codeLine, compilerConfiguration) }) {
467465
is ResultWithDiagnostics.Success -> {
468466
val compileResult = compileResultWithDiagnostics.value
469-
classWriter?.writeClasses(compileResult())
467+
classWriter?.writeClasses(codeLine, compileResult.get())
470468
val repl = this
471469
val currentEvalConfig = ScriptEvaluationConfiguration(evaluatorConfiguration) {
472470
constructorArgs.invoke(repl as KotlinKernelHost)
473471
}
474-
val result = evaluator.eval(compileResult, currentEvalConfig).valueOrThrow()
472+
val result = runBlocking { evaluator.eval(compileResult, currentEvalConfig).valueOrThrow() }
475473
contextUpdater.update()
476474

477-
val pureResult = result()
475+
val pureResult = result.get()
478476
return when {
479477
pureResult.isErrorResult -> throw ReplEvalRuntimeException(pureResult.error?.message.orEmpty(), pureResult.error)
480478
pureResult.isUnitResult -> {
481479
InternalEvalResult(Unit, null)
482480
}
483481
pureResult.isValueResult -> {
484-
InternalEvalResult(pureResult.result, pureResult.compiledSnippet().resultField)
482+
InternalEvalResult(pureResult.result, pureResult.compiledSnippet.resultField)
485483
}
486484
else -> throw IllegalStateException("Unknown eval result type ${this}")
487485
}

‎src/main/kotlin/org/jetbrains/kotlin/jupyter/repl/completion/KotlinCompleter.kt

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package org.jetbrains.kotlin.jupyter.repl.completion
22

33
import com.beust.klaxon.JsonObject
4+
import kotlinx.coroutines.runBlocking
45
import org.jetbrains.annotations.TestOnly
56
import org.jetbrains.kotlin.jupyter.jsonObject
67
import java.io.PrintWriter
78
import java.io.StringWriter
89
import kotlin.script.experimental.api.*
9-
import kotlin.script.experimental.util.ReplCompletionVariant
10-
import kotlin.script.experimental.util.ReplDiagnosticMessage
10+
import kotlin.script.experimental.util.toSourceCodePosition
1111

1212
enum class CompletionStatus(private val value: String) {
1313
OK("ok"),
@@ -30,7 +30,7 @@ abstract class CompletionResult(
3030
open class Success(
3131
private val matches: List<String>,
3232
private val bounds: CompletionTokenBounds,
33-
private val metadata: List<ReplCompletionVariant>,
33+
private val metadata: List<SourceCodeCompletionVariant>,
3434
private val text: String,
3535
private val cursor: Int
3636
): CompletionResult(CompletionStatus.OK) {
@@ -91,7 +91,7 @@ abstract class CompletionResult(
9191
}
9292
}
9393

94-
data class ListErrorsResult(val code: String, val errors: Iterable<ReplDiagnosticMessage> = emptyList()) {
94+
data class ListErrorsResult(val code: String, val errors: Sequence<ScriptDiagnostic> = emptySequence()) {
9595
fun toJson(): JsonObject {
9696
return jsonObject("code" to code,
9797
"errors" to errors.map {
@@ -100,7 +100,7 @@ data class ListErrorsResult(val code: String, val errors: Iterable<ReplDiagnosti
100100
"severity" to it.severity.name
101101
)
102102

103-
val loc = it.loc
103+
val loc = it.location
104104
if (loc != null) {
105105
val start = loc.start
106106
val end = loc.end
@@ -122,7 +122,7 @@ class KotlinCompleter {
122122
fun complete(compiler: ReplCompleter, configuration: ScriptCompilationConfiguration, code: String, id: Int, cursor: Int): CompletionResult {
123123
return try {
124124
val codeLine = SourceCodeImpl(id, code)
125-
val completionResult = compiler.complete(codeLine, cursor, configuration)
125+
val completionResult = runBlocking { compiler.complete(codeLine, cursor.toSourceCodePosition(codeLine), configuration) }
126126

127127
completionResult.valueOrNull()?.toList()?.let { completionList ->
128128
val bounds = getTokenBounds(code, cursor)

‎src/main/kotlin/org/jetbrains/kotlin/jupyter/repl/reflect/ContextUpdater.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import jupyter.kotlin.KotlinContext
44
import jupyter.kotlin.KotlinFunctionInfo
55
import jupyter.kotlin.KotlinVariableInfo
66
import org.jetbrains.kotlin.jupyter.instances
7-
import org.jetbrains.kotlin.scripting.ide_services.evaluator.KJvmReplEvaluatorImpl
87
import org.slf4j.LoggerFactory
98

109
import java.lang.reflect.Field
1110
import java.util.*
1211
import kotlin.reflect.jvm.kotlinFunction
1312
import kotlin.reflect.jvm.kotlinProperty
13+
import kotlin.script.experimental.jvm.KJvmReplEvaluatorImpl
1414

1515
/**
1616
* ContextUpdater updates current user-defined functions and variables

‎src/main/kotlin/org/jetbrains/kotlin/jupyter/repl/spark/ClassWriter.kt

+6-7
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
package org.jetbrains.kotlin.jupyter.repl.spark
22

3-
import org.jetbrains.kotlin.cli.common.repl.ReplCompileResult.CompiledClasses
43
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.KJvmCompiledModuleInMemory
54
import org.slf4j.LoggerFactory
65
import java.io.BufferedOutputStream
7-
import java.io.File
86
import java.io.FileOutputStream
97
import java.io.IOException
108
import java.nio.file.Files
119
import java.nio.file.Path
1210
import java.nio.file.Paths
11+
import kotlin.script.experimental.api.SourceCode
1312
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
1413

1514

@@ -32,11 +31,11 @@ class ClassWriter(_outputDir: String = "") {
3231
logger.info("Created ClassWriter with path <$outputDir>")
3332
}
3433

35-
fun writeClasses(classes: KJvmCompiledScript<*>) {
36-
writeModuleInMemory(classes)
34+
fun writeClasses(code: SourceCode, classes: KJvmCompiledScript<*>) {
35+
writeModuleInMemory(code, classes)
3736
}
3837

39-
private fun writeModuleInMemory(classes: KJvmCompiledScript<*>) {
38+
private fun writeModuleInMemory(code: SourceCode, classes: KJvmCompiledScript<*>) {
4039
try {
4140
val moduleInMemory = classes.compiledModule as KJvmCompiledModuleInMemory
4241
moduleInMemory.compilerOutputFiles.forEach { (name, bytes) ->
@@ -45,9 +44,9 @@ class ClassWriter(_outputDir: String = "") {
4544
}
4645
}
4746
} catch (e: ClassCastException) {
48-
logger.info("Compiled line " + classes.code.name + " has no in-memory modules")
47+
logger.info("Compiled line " + code.name + " has no in-memory modules")
4948
} catch (e: NullPointerException) {
50-
logger.info("Compiled line " + classes.code.name + " has no in-memory modules")
49+
logger.info("Compiled line " + code.name + " has no in-memory modules")
5150
}
5251
}
5352

‎src/main/kotlin/org/jetbrains/kotlin/jupyter/util.kt

+18-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package org.jetbrains.kotlin.jupyter
22

33
import kotlinx.coroutines.*
4-
import org.jetbrains.kotlin.scripting.ide_services.evaluator.KJvmEvaluatedSnippet
54
import org.slf4j.Logger
65
import java.io.File
7-
import kotlin.script.experimental.api.ILinkedPushStack
8-
import kotlin.script.experimental.api.toList
6+
import kotlin.script.experimental.api.ScriptDiagnostic
7+
import kotlin.script.experimental.api.SourceCode
8+
import kotlin.script.experimental.jvm.KJvmEvaluatedSnippet
9+
import kotlin.script.experimental.util.LinkedSnippet
10+
import kotlin.script.experimental.util.toList
911

1012
fun <T> catchAll(body: () -> T): T? = try {
1113
body()
@@ -46,4 +48,16 @@ fun File.tryReadIniConfig() =
4648

4749

4850

49-
fun ILinkedPushStack<KJvmEvaluatedSnippet>?.instances() = this.toList { it.snippetObject }.filterNotNull()
51+
fun LinkedSnippet<KJvmEvaluatedSnippet>?.instances() = this.toList { it.snippetObject }.filterNotNull()
52+
53+
fun generateDiagnostic(fromLine: Int, fromCol: Int, toLine: Int, toCol: Int, message: String, severity: String) =
54+
ScriptDiagnostic(
55+
ScriptDiagnostic.unspecifiedError,
56+
message,
57+
ScriptDiagnostic.Severity.valueOf(severity),
58+
null,
59+
SourceCode.Location(SourceCode.Position(fromLine, fromCol), SourceCode.Position(toLine, toCol))
60+
)
61+
62+
fun withPath(path: String?, diagnostics: List<ScriptDiagnostic>): List<ScriptDiagnostic> =
63+
diagnostics.map { it.copy(sourcePath = path) }

‎src/test/kotlin/org/jetbrains/kotlin/jupyter/test/replTests.kt

+8-7
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import org.junit.Assert
1111
import org.junit.Ignore
1212
import org.junit.Test
1313
import java.io.File
14-
import kotlin.script.experimental.util.ReplDiagnosticMessage
1514
import kotlin.script.experimental.api.SourceCode
1615
import kotlin.test.*
1716

@@ -186,12 +185,14 @@ class ReplTest {
186185
val b: Int = "str"
187186
val c = foob
188187
""".trimIndent()) {result ->
189-
Assert.assertEquals(listOf(
190-
ReplDiagnosticMessage(1, 16, 1, 20, "Type mismatch: inferred type is String but Int was expected", "ERROR"),
191-
ReplDiagnosticMessage(1, 22, 1, 26, "The floating-point literal does not conform to the expected type String", "ERROR"),
192-
ReplDiagnosticMessage(2, 14, 2, 19, "Type mismatch: inferred type is String but Int was expected", "ERROR"),
193-
ReplDiagnosticMessage(3, 9, 3, 13, "Unresolved reference: foob", "ERROR")
194-
), result.errors)
188+
val actualErrors = result.errors.toList()
189+
val path = actualErrors.first().sourcePath
190+
Assert.assertEquals(withPath(path, listOf(
191+
generateDiagnostic(1, 16, 1, 20, "Type mismatch: inferred type is String but Int was expected", "ERROR"),
192+
generateDiagnostic(1, 22, 1, 26, "The floating-point literal does not conform to the expected type String", "ERROR"),
193+
generateDiagnostic(2, 14, 2, 19, "Type mismatch: inferred type is String but Int was expected", "ERROR"),
194+
generateDiagnostic(3, 9, 3, 13, "Unresolved reference: foob", "ERROR")
195+
)), actualErrors)
195196
}
196197
}
197198
}

0 commit comments

Comments
 (0)
Please sign in to comment.