Add remote repl support to the daemon, refactor repl classes accordingly, simple tests

This commit is contained in:
Ilya Chernikov
2016-09-16 17:38:00 +02:00
parent 042fc4fadc
commit 86ece30330
12 changed files with 648 additions and 111 deletions
@@ -11,5 +11,6 @@
<orderEntry type="module" module-name="frontend.java" />
<orderEntry type="module" module-name="util" />
<orderEntry type="library" name="native-platform-uberjar" level="project" />
<orderEntry type="module" module-name="cli-common" />
</component>
</module>
@@ -31,7 +31,6 @@ import java.util.concurrent.TimeUnit
import kotlin.comparisons.compareByDescending
import kotlin.concurrent.thread
class CompilationServices(
val incrementalCompilationComponents: IncrementalCompilationComponents? = null,
val compilationCanceledStatus: CompilationCanceledStatus? = null
@@ -53,18 +52,12 @@ object KotlinCompilerClient {
autostart: Boolean = true,
checkId: Boolean = true
): CompileService? {
fun newFlagFile(): File {
val flagFile = File.createTempFile("kotlin-compiler-client-", "-is-running")
flagFile.deleteOnExit()
return flagFile
}
val flagFile = System.getProperty(COMPILE_DAEMON_CLIENT_ALIVE_PATH_PROPERTY)
?.let { it.trimQuotes() }
?.let(String::trimQuotes)
?.check { !it.isBlank() }
?.let { File(it) }
?.check { it.exists() }
?: newFlagFile()
?.let(::File)
?.check(File::exists)
?: makeAutodeletingFlagFile()
return connectToCompileService(compilerId, flagFile, daemonJVMOptions, daemonOptions, reportingTargets, autostart)
}
@@ -287,7 +280,7 @@ object KotlinCompilerClient {
val daemonLauncher = Native.get(ProcessLauncher::class.java)
val daemon = daemonLauncher.start(processBuilder)
var isEchoRead = Semaphore(1)
val isEchoRead = Semaphore(1)
isEchoRead.acquire()
val stdoutThread =
@@ -316,7 +309,7 @@ object KotlinCompilerClient {
it.toLong()
}
catch (e: Exception) {
reportingTargets.report(DaemonReportCategory.INFO, "unable to interpret ${COMPILE_DAEMON_STARTUP_TIMEOUT_PROPERTY} property ('$it'); using default timeout $DAEMON_DEFAULT_STARTUP_TIMEOUT_MS ms")
reportingTargets.report(DaemonReportCategory.INFO, "unable to interpret $COMPILE_DAEMON_STARTUP_TIMEOUT_PROPERTY property ('$it'); using default timeout $DAEMON_DEFAULT_STARTUP_TIMEOUT_MS ms")
null
}
} ?: DAEMON_DEFAULT_STARTUP_TIMEOUT_MS
@@ -0,0 +1,131 @@
/*
* Copyright 2010-2016 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.kotlin.daemon.client
import com.intellij.openapi.Disposable
import com.intellij.openapi.util.Disposer
import org.jetbrains.kotlin.cli.common.repl.*
import org.jetbrains.kotlin.daemon.common.CompileService
import org.jetbrains.kotlin.daemon.common.RemoteOperationsTracer
import org.jetbrains.kotlin.daemon.common.SOCKET_ANY_FREE_PORT
import java.io.File
import java.io.InputStream
import java.io.OutputStream
// TODO: reduce number of ports used then SOCKET_ANY_FREE_PORT is passed (same problem with other calls)
open class KotlinRemoteReplClientBase(
disposable: Disposable,
protected val compileService: CompileService,
clientAliveFlagFile: File?,
targetPlatform: CompileService.TargetPlatform,
templateClasspath: List<File>,
templateClassName: String,
compilerMessagesOutputStream: OutputStream,
evalOutputStream: OutputStream? = null,
evalErrorStream: OutputStream? = null,
evalInputStream: InputStream? = null,
port: Int = SOCKET_ANY_FREE_PORT,
operationsTracer: RemoteOperationsTracer? = null
) : ReplChecker {
val sessionId = compileService.leaseReplSession(
clientAliveFlagFile?.absolutePath,
targetPlatform,
CompilerCallbackServicesFacadeServer(port = port),
templateClasspath,
templateClassName,
RemoteOutputStreamServer(compilerMessagesOutputStream, port),
evalOutputStream?.let { RemoteOutputStreamServer(it, port) },
evalErrorStream?.let { RemoteOutputStreamServer(it, port) },
evalInputStream?.let { RemoteInputStreamServer(it, port) },
operationsTracer
).get()
init {
Disposer.register(disposable, Disposable {
compileService.releaseReplSession(sessionId)
})
}
override fun check(codeLine: ReplCodeLine, history: Iterable<ReplCodeLine>): ReplCheckResult {
return compileService.remoteReplLineCheck(sessionId, codeLine, history.toList()).get()
}
}
class KotlinRemoteReplCompiler(
disposable: Disposable,
compileService: CompileService,
clientAliveFlagFile: File?,
targetPlatform: CompileService.TargetPlatform,
templateClasspath: List<File>,
templateClassName: String,
compilerMessagesOutputStream: OutputStream,
port: Int = SOCKET_ANY_FREE_PORT,
operationsTracer: RemoteOperationsTracer? = null
) : KotlinRemoteReplClientBase(
disposable = disposable,
compileService = compileService,
clientAliveFlagFile = clientAliveFlagFile,
targetPlatform = targetPlatform,
templateClasspath = templateClasspath,
templateClassName = templateClassName,
compilerMessagesOutputStream = compilerMessagesOutputStream,
evalOutputStream = null,
evalErrorStream = null,
evalInputStream = null,
port = port,
operationsTracer = operationsTracer
), ReplCompiler {
override fun compile(codeLine: ReplCodeLine, history: Iterable<ReplCodeLine>): ReplCompileResult {
return compileService.remoteReplLineCompile(sessionId, codeLine, history.toList()).get()
}
}
class KotlinRemoteReplEvaluator(
disposable: Disposable,
compileService: CompileService,
clientAliveFlagFile: File?,
targetPlatform: CompileService.TargetPlatform,
templateClasspath: List<File>,
templateClassName: String,
compilerMessagesOutputStream: OutputStream,
evalOutputStream: OutputStream?,
evalErrorStream: OutputStream?,
evalInputStream: InputStream?,
port: Int = SOCKET_ANY_FREE_PORT,
operationsTracer: RemoteOperationsTracer? = null
) : KotlinRemoteReplClientBase(
disposable = disposable,
compileService = compileService,
clientAliveFlagFile = clientAliveFlagFile,
targetPlatform = targetPlatform,
templateClasspath = templateClasspath,
templateClassName = templateClassName,
compilerMessagesOutputStream = compilerMessagesOutputStream,
evalOutputStream = evalOutputStream,
evalErrorStream = evalErrorStream,
evalInputStream = evalInputStream,
port = port,
operationsTracer = operationsTracer
), ReplEvaluator {
override fun eval(codeLine: ReplCodeLine, history: Iterable<ReplCodeLine>): ReplEvalResult {
return compileService.remoteReplLineEval(sessionId, codeLine, history.toList()).get()
}
}