Get rid of daemon-client dependency on openapi, making others "provided"

(cherry picked from commit 175d74c)
This commit is contained in:
Ilya Chernikov
2017-02-09 16:36:18 +01:00
parent f6fd9441e9
commit 46894da981
7 changed files with 67 additions and 91 deletions
@@ -7,11 +7,10 @@
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="daemon-common" /> <orderEntry type="module" module-name="daemon-common" scope="PROVIDED" />
<orderEntry type="module" module-name="util" /> <orderEntry type="module" module-name="util" scope="PROVIDED" />
<orderEntry type="library" name="native-platform-uberjar" level="project" /> <orderEntry type="library" scope="PROVIDED" name="native-platform-uberjar" level="project" />
<orderEntry type="module" module-name="cli-common" /> <orderEntry type="module" module-name="cli-common" scope="PROVIDED" />
<orderEntry type="module" module-name="descriptors" /> <orderEntry type="module" module-name="descriptors" scope="PROVIDED" />
<orderEntry type="library" name="intellij-core" level="project" />
</component> </component>
</module> </module>
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.daemon.client package org.jetbrains.kotlin.daemon.client
import com.intellij.openapi.progress.ProcessCanceledException
import org.jetbrains.kotlin.daemon.common.CompilerCallbackServicesFacade import org.jetbrains.kotlin.daemon.common.CompilerCallbackServicesFacade
import org.jetbrains.kotlin.daemon.common.LoopbackNetworkInterface import org.jetbrains.kotlin.daemon.common.LoopbackNetworkInterface
import org.jetbrains.kotlin.daemon.common.RmiFriendlyCompilationCanceledException import org.jetbrains.kotlin.daemon.common.RmiFriendlyCompilationCanceledException
@@ -27,7 +26,9 @@ import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompil
import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto
import org.jetbrains.kotlin.modules.TargetId import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.progress.CompilationCanceledStatus import org.jetbrains.kotlin.progress.CompilationCanceledStatus
import org.jetbrains.kotlin.utils.rethrow
import java.rmi.server.UnicastRemoteObject import java.rmi.server.UnicastRemoteObject
import kotlin.reflect.full.allSuperclasses
open class CompilerCallbackServicesFacadeServer( open class CompilerCallbackServicesFacadeServer(
@@ -83,10 +84,12 @@ open class CompilerCallbackServicesFacadeServer(
try { try {
compilationCanceledStatus!!.checkCanceled() compilationCanceledStatus!!.checkCanceled()
} }
catch (e: ProcessCanceledException) { catch (e: Exception) {
// avoid passing exceptions that may have different serialVersionUID on across rmi border // avoid passing exceptions that may have different serialVersionUID on across rmi border
// TODO: doublecheck whether we need to distinguish different cancellation exceptions // removing dependency from openapi (this is obsolete part anyway, and will be removed soon)
throw RmiFriendlyCompilationCanceledException() if ((e::class.allSuperclasses + e::class).any { it.qualifiedName == "com.intellij.openapi.progress.ProcessCanceledException" })
throw RmiFriendlyCompilationCanceledException()
else throw e
} }
} }
} }
@@ -16,8 +16,6 @@
package org.jetbrains.kotlin.daemon.client 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.cli.common.repl.*
import org.jetbrains.kotlin.daemon.common.CompileService import org.jetbrains.kotlin.daemon.common.CompileService
import org.jetbrains.kotlin.daemon.common.RemoteOperationsTracer import org.jetbrains.kotlin.daemon.common.RemoteOperationsTracer
@@ -29,7 +27,6 @@ import java.io.OutputStream
// TODO: reduce number of ports used then SOCKET_ANY_FREE_PORT is passed (same problem with other calls) // TODO: reduce number of ports used then SOCKET_ANY_FREE_PORT is passed (same problem with other calls)
open class KotlinRemoteReplClientBase( open class KotlinRemoteReplClientBase(
disposable: Disposable,
protected val compileService: CompileService, protected val compileService: CompileService,
clientAliveFlagFile: File?, clientAliveFlagFile: File?,
targetPlatform: CompileService.TargetPlatform, targetPlatform: CompileService.TargetPlatform,
@@ -60,20 +57,18 @@ open class KotlinRemoteReplClientBase(
operationsTracer operationsTracer
).get() ).get()
init { // dispose should be called at the end of the repl lifetime to free daemon repl session and appropriate resources
Disposer.register(disposable, Disposable { open fun dispose() {
try { try {
compileService.releaseReplSession(sessionId) compileService.releaseReplSession(sessionId)
} }
catch (ex: java.rmi.RemoteException) { catch (ex: java.rmi.RemoteException) {
// assuming that communication failed and daemon most likely is already down // assuming that communication failed and daemon most likely is already down
} }
})
} }
} }
class KotlinRemoteReplCompiler( class KotlinRemoteReplCompiler(
disposable: Disposable,
compileService: CompileService, compileService: CompileService,
clientAliveFlagFile: File?, clientAliveFlagFile: File?,
targetPlatform: CompileService.TargetPlatform, targetPlatform: CompileService.TargetPlatform,
@@ -83,7 +78,6 @@ class KotlinRemoteReplCompiler(
port: Int = SOCKET_ANY_FREE_PORT, port: Int = SOCKET_ANY_FREE_PORT,
operationsTracer: RemoteOperationsTracer? = null operationsTracer: RemoteOperationsTracer? = null
) : KotlinRemoteReplClientBase( ) : KotlinRemoteReplClientBase(
disposable = disposable,
compileService = compileService, compileService = compileService,
clientAliveFlagFile = clientAliveFlagFile, clientAliveFlagFile = clientAliveFlagFile,
targetPlatform = targetPlatform, targetPlatform = targetPlatform,
@@ -114,7 +108,6 @@ class KotlinRemoteReplCompiler(
// TODO: consider removing daemon eval completely - it is not required now and has questionable security. This will simplify daemon interface as well // TODO: consider removing daemon eval completely - it is not required now and has questionable security. This will simplify daemon interface as well
class KotlinRemoteReplEvaluator( class KotlinRemoteReplEvaluator(
disposable: Disposable,
compileService: CompileService, compileService: CompileService,
clientAliveFlagFile: File?, clientAliveFlagFile: File?,
targetPlatform: CompileService.TargetPlatform, targetPlatform: CompileService.TargetPlatform,
@@ -129,7 +122,6 @@ class KotlinRemoteReplEvaluator(
port: Int = SOCKET_ANY_FREE_PORT, port: Int = SOCKET_ANY_FREE_PORT,
operationsTracer: RemoteOperationsTracer? = null operationsTracer: RemoteOperationsTracer? = null
) : KotlinRemoteReplClientBase( ) : KotlinRemoteReplClientBase(
disposable = disposable,
compileService = compileService, compileService = compileService,
clientAliveFlagFile = clientAliveFlagFile, clientAliveFlagFile = clientAliveFlagFile,
targetPlatform = targetPlatform, targetPlatform = targetPlatform,
@@ -16,8 +16,6 @@
package org.jetbrains.kotlin.daemon package org.jetbrains.kotlin.daemon
import com.intellij.openapi.Disposable
import com.intellij.openapi.util.Disposer
import junit.framework.TestCase import junit.framework.TestCase
import org.jetbrains.kotlin.cli.AbstractCliTest import org.jetbrains.kotlin.cli.AbstractCliTest
import org.jetbrains.kotlin.cli.common.repl.* import org.jetbrains.kotlin.cli.common.repl.*
@@ -480,32 +478,30 @@ class CompilerDaemonTest : KotlinIntegrationTestBase() {
fun testDaemonReplLocalEvalNoParams() { fun testDaemonReplLocalEvalNoParams() {
withDaemon { daemon -> withDaemon { daemon ->
withDisposable { disposable -> val repl = KotlinRemoteReplCompiler(daemon, null, CompileService.TargetPlatform.JVM,
val repl = KotlinRemoteReplCompiler(disposable, daemon!!, null, CompileService.TargetPlatform.JVM, classpathFromClassloader(),
classpathFromClassloader(), ScriptWithNoParam::class.qualifiedName!!,
ScriptWithNoParam::class.qualifiedName!!, System.err)
System.err)
val localEvaluator = GenericReplEvaluator(emptyList(), Thread.currentThread().contextClassLoader) val localEvaluator = GenericReplEvaluator(emptyList(), Thread.currentThread().contextClassLoader)
doReplTestWithLocalEval(repl, localEvaluator) doReplTestWithLocalEval(repl, localEvaluator)
} repl.dispose()
} }
} }
fun testDaemonReplLocalEvalStandardTemplate() { fun testDaemonReplLocalEvalStandardTemplate() {
withDaemon { daemon -> withDaemon { daemon ->
withDisposable { disposable -> val repl = KotlinRemoteReplCompiler(daemon, null, CompileService.TargetPlatform.JVM,
val repl = KotlinRemoteReplCompiler(disposable, daemon!!, null, CompileService.TargetPlatform.JVM, classpathFromClassloader(),
classpathFromClassloader(), "kotlin.script.templates.standard.ScriptTemplateWithArgs",
"kotlin.script.templates.standard.ScriptTemplateWithArgs", System.err)
System.err)
val localEvaluator = GenericReplEvaluator(emptyList(), Thread.currentThread().contextClassLoader, val localEvaluator = GenericReplEvaluator(emptyList(), Thread.currentThread().contextClassLoader,
ScriptArgsWithTypes(arrayOf(emptyArray<String>()), arrayOf(Array<String>::class))) ScriptArgsWithTypes(arrayOf(emptyArray<String>()), arrayOf(Array<String>::class)))
doReplTestWithLocalEval(repl, localEvaluator) doReplTestWithLocalEval(repl, localEvaluator)
} repl.dispose()
} }
} }
@@ -538,36 +534,34 @@ class CompilerDaemonTest : KotlinIntegrationTestBase() {
fun testDaemonReplRemoteEval() { fun testDaemonReplRemoteEval() {
withDaemon { daemon -> withDaemon { daemon ->
withDisposable { disposable -> val evalOut = ByteArrayOutputStream()
val evalErr = ByteArrayOutputStream()
val evalIn = ByteArrayInputStream("42\n".toByteArray())
val evalOut = ByteArrayOutputStream() val repl = KotlinRemoteReplEvaluator(daemon, null, CompileService.TargetPlatform.JVM,
val evalErr = ByteArrayOutputStream() listOf(File(KotlinIntegrationTestBase.getCompilerLib(), "kotlin-runtime.jar")),
val evalIn = ByteArrayInputStream("42\n".toByteArray()) "kotlin.script.templates.standard.ScriptTemplateWithArgs",
arrayOf(emptyArray<String>()),
arrayOf(Array<String>::class.java),
System.err, evalOut, evalErr, evalIn)
val repl = KotlinRemoteReplEvaluator(disposable, daemon!!, null, CompileService.TargetPlatform.JVM, val res0 = repl.check(ReplCodeLine(0, "val x ="))
listOf(File(KotlinIntegrationTestBase.getCompilerLib(), "kotlin-runtime.jar")), TestCase.assertTrue("Unexpected check results: $res0", res0 is ReplCheckResult.Incomplete)
"kotlin.script.templates.standard.ScriptTemplateWithArgs",
arrayOf(emptyArray<String>()),
arrayOf(Array<String>::class.java),
System.err, evalOut, evalErr, evalIn)
val res0 = repl.check(ReplCodeLine(0, "val x =")) val codeLine1 = ReplCodeLine(1, "val x = 5")
TestCase.assertTrue("Unexpected check results: $res0", res0 is ReplCheckResult.Incomplete) val res1 = repl.compileAndEval(codeLine1, verifyHistory = emptyList())
val res1e = res1 as? ReplEvalResult.UnitResult
TestCase.assertNotNull("Unexpected eval result: $res1", res1e)
val codeLine1 = ReplCodeLine(1, "val x = 5") val codeLine2 = ReplCodeLine(2, "x + 2")
val res1 = repl.compileAndEval(codeLine1, verifyHistory = emptyList()) val res2x = repl.compileAndEval(codeLine2, verifyHistory = listOf(codeLine2))
val res1e = res1 as? ReplEvalResult.UnitResult TestCase.assertNotNull("Unexpected compile result: $res2x", res2x as? ReplEvalResult.HistoryMismatch)
TestCase.assertNotNull("Unexpected eval result: $res1", res1e)
val codeLine2 = ReplCodeLine(2, "x + 2") val res2 = repl.compileAndEval(codeLine2, verifyHistory = listOf(codeLine1))
val res2x = repl.compileAndEval(codeLine2, verifyHistory = listOf(codeLine2)) val res2e = res2 as? ReplEvalResult.ValueResult
TestCase.assertNotNull("Unexpected compile result: $res2x", res2x as? ReplEvalResult.HistoryMismatch) TestCase.assertNotNull("Unexpected eval result: $res2", res2e)
TestCase.assertEquals(7, res2e!!.value)
val res2 = repl.compileAndEval(codeLine2, verifyHistory = listOf(codeLine1)) repl.dispose()
val res2e = res2 as? ReplEvalResult.ValueResult
TestCase.assertNotNull("Unexpected eval result: $res2", res2e)
TestCase.assertEquals(7, res2e!!.value)
}
} }
} }
@@ -584,8 +578,7 @@ class CompilerDaemonTest : KotlinIntegrationTestBase() {
val daemon = KotlinCompilerClient.connectToCompileService(compilerId, flagFile, daemonJVMOptions, daemonOptions, DaemonReportingTargets(out = System.err), autostart = true) val daemon = KotlinCompilerClient.connectToCompileService(compilerId, flagFile, daemonJVMOptions, daemonOptions, DaemonReportingTargets(out = System.err), autostart = true)
assertNotNull("failed to connect daemon", daemon) assertNotNull("failed to connect daemon", daemon)
val disposable = Disposer.newDisposable() val repl = KotlinRemoteReplCompiler(daemon!!, null, CompileService.TargetPlatform.JVM,
val repl = KotlinRemoteReplCompiler(disposable, daemon!!, null, CompileService.TargetPlatform.JVM,
classpathFromClassloader(), classpathFromClassloader(),
ScriptWithNoParam::class.qualifiedName!!, ScriptWithNoParam::class.qualifiedName!!,
System.err) System.err)
@@ -604,7 +597,7 @@ class CompilerDaemonTest : KotlinIntegrationTestBase() {
if (logFile.isLogContainsSequence("Idle timeout exceeded 1s")) break if (logFile.isLogContainsSequence("Idle timeout exceeded 1s")) break
Thread.sleep(200) Thread.sleep(200)
} }
Disposer.dispose(disposable) repl.dispose()
Thread.sleep(200) Thread.sleep(200)
logFile.assertLogContainsSequence("Idle timeout exceeded 1s", logFile.assertLogContainsSequence("Idle timeout exceeded 1s",
@@ -688,16 +681,6 @@ internal inline fun withFlagFile(prefix: String, suffix: String? = null, body: (
} }
} }
internal inline fun withDisposable(body: (Disposable) -> Unit) {
val disposable = Disposer.newDisposable()
try {
body(disposable)
}
finally {
Disposer.dispose(disposable)
}
}
// java.util.Logger used in the daemon silently forgets to log into a file specified in the config on Windows, // java.util.Logger used in the daemon silently forgets to log into a file specified in the config on Windows,
// if file path is given in windows form (using backslash as a separator); the reason is unknown // if file path is given in windows form (using backslash as a separator); the reason is unknown
// this function makes a path with forward slashed, that works on windows too // this function makes a path with forward slashed, that works on windows too
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.jsr223 package org.jetbrains.kotlin.jsr223
import com.intellij.openapi.Disposable
import org.jetbrains.kotlin.cli.common.repl.* import org.jetbrains.kotlin.cli.common.repl.*
import org.jetbrains.kotlin.daemon.client.DaemonReportMessage import org.jetbrains.kotlin.daemon.client.DaemonReportMessage
import org.jetbrains.kotlin.daemon.client.DaemonReportingTargets import org.jetbrains.kotlin.daemon.client.DaemonReportingTargets
@@ -30,8 +29,9 @@ import javax.script.ScriptEngineFactory
import javax.script.ScriptException import javax.script.ScriptException
import kotlin.reflect.KClass import kotlin.reflect.KClass
// TODO: need to manage resources here, i.e. call replCompiler.dispose when engine is collected
class KotlinJsr223JvmScriptEngine4Idea( class KotlinJsr223JvmScriptEngine4Idea(
disposable: Disposable,
factory: ScriptEngineFactory, factory: ScriptEngineFactory,
templateClasspath: List<File>, templateClasspath: List<File>,
templateClassName: String, templateClassName: String,
@@ -54,8 +54,7 @@ class KotlinJsr223JvmScriptEngine4Idea(
override val replCompiler: ReplCompiler by lazy { override val replCompiler: ReplCompiler by lazy {
daemon.let { daemon.let {
KotlinRemoteReplCompiler(disposable, KotlinRemoteReplCompiler(it,
it,
makeAutodeletingFlagFile("idea-jsr223-repl-session"), makeAutodeletingFlagFile("idea-jsr223-repl-session"),
CompileService.TargetPlatform.JVM, CompileService.TargetPlatform.JVM,
templateClasspath, templateClasspath,
@@ -16,11 +16,11 @@
package org.jetbrains.kotlin.jsr223 package org.jetbrains.kotlin.jsr223
import com.intellij.openapi.util.Disposer
import org.jetbrains.kotlin.cli.common.repl.KotlinJsr223JvmScriptEngineFactoryBase import org.jetbrains.kotlin.cli.common.repl.KotlinJsr223JvmScriptEngineFactoryBase
import org.jetbrains.kotlin.cli.common.repl.ScriptArgsWithTypes import org.jetbrains.kotlin.cli.common.repl.ScriptArgsWithTypes
import org.jetbrains.kotlin.utils.PathUtil import org.jetbrains.kotlin.utils.PathUtil
import org.jetbrains.kotlin.utils.PathUtil.* import org.jetbrains.kotlin.utils.PathUtil.KOTLIN_JAVA_SCRIPT_RUNTIME_JAR
import org.jetbrains.kotlin.utils.PathUtil.KOTLIN_JAVA_STDLIB_JAR
import java.io.File import java.io.File
import java.io.FileNotFoundException import java.io.FileNotFoundException
import java.net.URL import java.net.URL
@@ -33,7 +33,6 @@ class KotlinJsr223StandardScriptEngineFactory4Idea : KotlinJsr223JvmScriptEngine
override fun getScriptEngine(): ScriptEngine = override fun getScriptEngine(): ScriptEngine =
KotlinJsr223JvmScriptEngine4Idea( KotlinJsr223JvmScriptEngine4Idea(
Disposer.newDisposable(),
this, this,
scriptCompilationClasspathFromContext(Thread.currentThread().contextClassLoader), scriptCompilationClasspathFromContext(Thread.currentThread().contextClassLoader),
"kotlin.script.templates.standard.ScriptTemplateWithBindings", "kotlin.script.templates.standard.ScriptTemplateWithBindings",
@@ -30,6 +30,8 @@ import javax.script.ScriptEngineFactory
import javax.script.ScriptException import javax.script.ScriptException
import kotlin.reflect.KClass import kotlin.reflect.KClass
// TODO: need to manage resources here, i.e. call replCompiler.dispose when engine is collected
class KotlinJsr223JvmDaemonCompileScriptEngine( class KotlinJsr223JvmDaemonCompileScriptEngine(
disposable: Disposable, disposable: Disposable,
factory: ScriptEngineFactory, factory: ScriptEngineFactory,
@@ -46,7 +48,6 @@ class KotlinJsr223JvmDaemonCompileScriptEngine(
override val replCompiler by lazy { override val replCompiler by lazy {
daemon.let { daemon.let {
KotlinRemoteReplCompiler( KotlinRemoteReplCompiler(
disposable,
it, it,
makeAutodeletingFlagFile("jsr223-repl-session"), makeAutodeletingFlagFile("jsr223-repl-session"),
CompileService.TargetPlatform.JVM, CompileService.TargetPlatform.JVM,