Refactoring parts related to passing services to compiler in daemon, adding uniform support for cancellation check and lookup tracking

This commit is contained in:
Ilya Chernikov
2015-09-23 15:07:48 +02:00
parent 3c16b2de87
commit 4b1601974f
11 changed files with 301 additions and 67 deletions
@@ -16,8 +16,9 @@
package org.jetbrains.kotlin.rmi.kotlinr package org.jetbrains.kotlin.rmi.kotlinr
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
import org.jetbrains.kotlin.modules.TargetId import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
import org.jetbrains.kotlin.rmi.* import org.jetbrains.kotlin.rmi.*
import java.io.* import java.io.*
import java.rmi.ConnectException import java.rmi.ConnectException
@@ -27,6 +28,12 @@ import java.util.concurrent.TimeUnit
import kotlin.concurrent.thread import kotlin.concurrent.thread
public class CompilationServices(
val incrementalCompilationComponents: IncrementalCompilationComponents? = null,
val compilationCanceledStatus: CompilationCanceledStatus? = null
)
public object KotlinCompilerClient { public object KotlinCompilerClient {
val DAEMON_DEFAULT_STARTUP_TIMEOUT_MS = 10000L val DAEMON_DEFAULT_STARTUP_TIMEOUT_MS = 10000L
@@ -108,7 +115,7 @@ public object KotlinCompilerClient {
val outStrm = RemoteOutputStreamServer(out) val outStrm = RemoteOutputStreamServer(out)
try { try {
return compiler.remoteCompile(args, outStrm, CompileService.OutputFormat.PLAIN, outStrm) return compiler.remoteCompile(args, makeRemoteServices(CompilationServices()), outStrm, CompileService.OutputFormat.PLAIN, outStrm)
} }
finally { finally {
outStrm.disconnect() outStrm.disconnect()
@@ -118,14 +125,13 @@ public object KotlinCompilerClient {
// TODO: remove jvmStatic after all use sites will switch to kotlin // TODO: remove jvmStatic after all use sites will switch to kotlin
@JvmStatic @JvmStatic
public fun incrementalCompile(compiler: CompileService, args: Array<out String>, caches: Map<TargetId, IncrementalCache>, compilerOut: OutputStream, daemonOut: OutputStream): Int { public fun incrementalCompile(compiler: CompileService, args: Array<out String>, services: CompilationServices, compilerOut: OutputStream, daemonOut: OutputStream): Int {
val compilerOutStreamServer = RemoteOutputStreamServer(compilerOut) val compilerOutStreamServer = RemoteOutputStreamServer(compilerOut)
val daemonOutStreamServer = RemoteOutputStreamServer(daemonOut) val daemonOutStreamServer = RemoteOutputStreamServer(daemonOut)
val cacheServers = hashMapOf<TargetId, RemoteIncrementalCacheServer>() val cacheServers = hashMapOf<TargetId, RemoteIncrementalCacheServer>()
try { try {
caches.mapValuesTo(cacheServers, { RemoteIncrementalCacheServer(it.getValue()) }) return compiler.remoteIncrementalCompile(args, makeRemoteServices(services), compilerOutStreamServer, CompileService.OutputFormat.XML, daemonOutStreamServer)
return compiler.remoteIncrementalCompile(args, cacheServers, compilerOutStreamServer, CompileService.OutputFormat.XML, daemonOutStreamServer)
} }
finally { finally {
cacheServers.forEach { it.getValue().disconnect() } cacheServers.forEach { it.getValue().disconnect() }
@@ -135,6 +141,12 @@ public object KotlinCompilerClient {
} }
fun makeRemoteServices(services: CompilationServices): CompileService.RemoteCompilationServices =
CompileService.RemoteCompilationServices(
incrementalCompilationComponents = if (services.incrementalCompilationComponents == null) null else RemoteIncrementalCompilationComponentsServer(services.incrementalCompilationComponents),
compilationCanceledStatus = if (services.compilationCanceledStatus == null) null else RemoteCompilationCanceledStatusServer(services.compilationCanceledStatus)
)
data class ClientOptions( data class ClientOptions(
public var stop: Boolean = false public var stop: Boolean = false
) : OptionsGroup { ) : OptionsGroup {
@@ -196,7 +208,7 @@ public object KotlinCompilerClient {
val memBefore = daemon.getUsedMemory() / 1024 val memBefore = daemon.getUsedMemory() / 1024
val startTime = System.nanoTime() val startTime = System.nanoTime()
val res = daemon.remoteCompile(filteredArgs.toArrayList().toTypedArray(), outStrm, CompileService.OutputFormat.PLAIN, outStrm) val res = daemon.remoteCompile(filteredArgs.toArrayList().toTypedArray(), makeRemoteServices(CompilationServices()), outStrm, CompileService.OutputFormat.PLAIN, outStrm)
val endTime = System.nanoTime() val endTime = System.nanoTime()
println("Compilation result code: $res") println("Compilation result code: $res")
@@ -0,0 +1,35 @@
/*
* Copyright 2010-2015 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.rmi.kotlinr
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
import org.jetbrains.kotlin.rmi.CompileService
import org.jetbrains.kotlin.rmi.LoopbackNetworkInterface
import org.jetbrains.kotlin.rmi.SOCKET_ANY_FREE_PORT
import java.rmi.server.UnicastRemoteObject
public class RemoteCompilationCanceledStatusServer(val base: CompilationCanceledStatus, port: Int = SOCKET_ANY_FREE_PORT) : CompileService.RemoteCompilationCanceledStatus {
init {
UnicastRemoteObject.exportObject(this, port, LoopbackNetworkInterface.clientLoopbackSocketFactory, LoopbackNetworkInterface.serverLoopbackSocketFactory)
}
override fun checkCanceled() {
base.checkCanceled()
}
}
@@ -0,0 +1,44 @@
/*
* Copyright 2010-2015 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.rmi.kotlinr
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.rmi.CompileService
import org.jetbrains.kotlin.rmi.LoopbackNetworkInterface
import org.jetbrains.kotlin.rmi.SOCKET_ANY_FREE_PORT
import java.rmi.server.UnicastRemoteObject
public class RemoteIncrementalCompilationComponentsServer(val base: IncrementalCompilationComponents, val port: Int = SOCKET_ANY_FREE_PORT) : CompileService.RemoteIncrementalCompilationComponents {
init {
UnicastRemoteObject.exportObject(this, port, LoopbackNetworkInterface.clientLoopbackSocketFactory, LoopbackNetworkInterface.serverLoopbackSocketFactory)
}
private val cacheServers = hashMapOf<TargetId, RemoteIncrementalCacheServer>()
private val lookupTrackerServer by lazy { RemoteLookupTrackerServer(base.getLookupTracker()) }
override fun getIncrementalCache(target: TargetId): CompileService.RemoteIncrementalCache =
cacheServers.get(target) ?: {
val newServer = RemoteIncrementalCacheServer(base.getIncrementalCache(target), port)
cacheServers.put(target, newServer)
newServer
}()
override fun getLookupTracker(): CompileService.RemoteLookupTracker = lookupTrackerServer
}
@@ -0,0 +1,40 @@
/*
* Copyright 2010-2015 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.rmi.kotlinr
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.components.ScopeKind
import org.jetbrains.kotlin.rmi.CompileService
import org.jetbrains.kotlin.rmi.LoopbackNetworkInterface
import org.jetbrains.kotlin.rmi.SOCKET_ANY_FREE_PORT
import java.rmi.server.UnicastRemoteObject
public class RemoteLookupTrackerServer(val base: LookupTracker, port: Int = SOCKET_ANY_FREE_PORT) : CompileService.RemoteLookupTracker {
init {
UnicastRemoteObject.exportObject(this, port, LoopbackNetworkInterface.clientLoopbackSocketFactory, LoopbackNetworkInterface.serverLoopbackSocketFactory)
}
override fun record(lookupContainingFile: String, lookupLine: Int?, lookupColumn: Int?, scopeFqName: String, scopeKind: ScopeKind, name: String) {
base.record(lookupContainingFile, lookupLine, lookupColumn, scopeFqName, scopeKind, name)
}
private val _isDoNothing: Boolean = base == LookupTracker.DO_NOTHING
override fun isDoNothing(): Boolean = _isDoNothing
}
@@ -16,7 +16,9 @@
package org.jetbrains.kotlin.rmi package org.jetbrains.kotlin.rmi
import org.jetbrains.kotlin.incremental.components.ScopeKind
import org.jetbrains.kotlin.modules.TargetId import org.jetbrains.kotlin.modules.TargetId
import java.io.Serializable
import java.rmi.Remote import java.rmi.Remote
import java.rmi.RemoteException import java.rmi.RemoteException
@@ -47,6 +49,38 @@ public interface CompileService : Remote {
public fun close() public fun close()
} }
public interface RemoteLookupTracker : Remote {
@Throws(RemoteException::class)
fun record(
lookupContainingFile: String,
lookupLine: Int?,
lookupColumn: Int?,
scopeFqName: String,
scopeKind: ScopeKind,
name: String
)
@Throws(RemoteException::class)
fun isDoNothing(): Boolean
}
public interface RemoteIncrementalCompilationComponents : Remote {
@Throws(RemoteException::class)
public fun getIncrementalCache(target: TargetId): RemoteIncrementalCache
@Throws(RemoteException::class)
public fun getLookupTracker(): RemoteLookupTracker
}
public interface RemoteCompilationCanceledStatus : Remote {
@Throws(RemoteException::class)
fun checkCanceled(): Unit
}
public data class RemoteCompilationServices(
public val incrementalCompilationComponents: RemoteIncrementalCompilationComponents? = null,
public val compilationCanceledStatus: RemoteCompilationCanceledStatus? = null
) : Serializable
@Throws(RemoteException::class) @Throws(RemoteException::class)
public fun getCompilerId(): CompilerId public fun getCompilerId(): CompilerId
@@ -59,6 +93,7 @@ public interface CompileService : Remote {
@Throws(RemoteException::class) @Throws(RemoteException::class)
public fun remoteCompile( public fun remoteCompile(
args: Array<out String>, args: Array<out String>,
services: RemoteCompilationServices,
compilerOutputStream: RemoteOutputStream, compilerOutputStream: RemoteOutputStream,
outputFormat: OutputFormat, outputFormat: OutputFormat,
serviceOutputStream: RemoteOutputStream serviceOutputStream: RemoteOutputStream
@@ -67,7 +102,7 @@ public interface CompileService : Remote {
@Throws(RemoteException::class) @Throws(RemoteException::class)
public fun remoteIncrementalCompile( public fun remoteIncrementalCompile(
args: Array<out String>, args: Array<out String>,
caches: Map<TargetId, RemoteIncrementalCache>, services: RemoteCompilationServices,
compilerOutputStream: RemoteOutputStream, compilerOutputStream: RemoteOutputStream,
compilerOutputFormat: OutputFormat, compilerOutputFormat: OutputFormat,
serviceOutputStream: RemoteOutputStream serviceOutputStream: RemoteOutputStream
@@ -19,22 +19,17 @@ package org.jetbrains.kotlin.rmi.service
import org.jetbrains.kotlin.cli.common.CLICompiler import org.jetbrains.kotlin.cli.common.CLICompiler
import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.config.Services
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
import org.jetbrains.kotlin.modules.TargetId import org.jetbrains.kotlin.progress.CompilationCanceledStatus
import org.jetbrains.kotlin.rmi.* import org.jetbrains.kotlin.rmi.*
import java.io.IOException
import java.io.PrintStream import java.io.PrintStream
import java.lang.management.ManagementFactory import java.lang.management.ManagementFactory
import java.lang.management.ThreadMXBean import java.lang.management.ThreadMXBean
import java.net.URLClassLoader
import java.rmi.NoSuchObjectException import java.rmi.NoSuchObjectException
import java.rmi.registry.Registry import java.rmi.registry.Registry
import java.rmi.server.UnicastRemoteObject import java.rmi.server.UnicastRemoteObject
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import java.util.concurrent.locks.ReentrantReadWriteLock import java.util.concurrent.locks.ReentrantReadWriteLock
import java.util.jar.Manifest
import java.util.logging.Logger import java.util.logging.Logger
import kotlin.concurrent.read import kotlin.concurrent.read
import kotlin.concurrent.write import kotlin.concurrent.write
@@ -65,6 +60,7 @@ class CompileServiceImpl<Compiler: CLICompiler<*>>(
} }
override fun remoteCompile(args: Array<out String>, override fun remoteCompile(args: Array<out String>,
services: CompileService.RemoteCompilationServices,
compilerOutputStream: RemoteOutputStream, compilerOutputStream: RemoteOutputStream,
outputFormat: CompileService.OutputFormat, outputFormat: CompileService.OutputFormat,
serviceOutputStream: RemoteOutputStream serviceOutputStream: RemoteOutputStream
@@ -77,7 +73,7 @@ class CompileServiceImpl<Compiler: CLICompiler<*>>(
} }
override fun remoteIncrementalCompile(args: Array<out String>, override fun remoteIncrementalCompile(args: Array<out String>,
caches: Map<TargetId, CompileService.RemoteIncrementalCache>, services: CompileService.RemoteCompilationServices,
compilerOutputStream: RemoteOutputStream, compilerOutputStream: RemoteOutputStream,
compilerOutputFormat: CompileService.OutputFormat, compilerOutputFormat: CompileService.OutputFormat,
serviceOutputStream: RemoteOutputStream serviceOutputStream: RemoteOutputStream
@@ -85,7 +81,7 @@ class CompileServiceImpl<Compiler: CLICompiler<*>>(
doCompile(args, compilerOutputStream, serviceOutputStream) { printStream -> doCompile(args, compilerOutputStream, serviceOutputStream) { printStream ->
when (compilerOutputFormat) { when (compilerOutputFormat) {
CompileService.OutputFormat.PLAIN -> throw NotImplementedError("Only XML output is supported in remote incremental compilation") CompileService.OutputFormat.PLAIN -> throw NotImplementedError("Only XML output is supported in remote incremental compilation")
CompileService.OutputFormat.XML -> compiler.execAndOutputXml(printStream, createCompileServices(caches), *args) CompileService.OutputFormat.XML -> compiler.execAndOutputXml(printStream, createCompileServices(services), *args)
} }
} }
@@ -127,13 +123,6 @@ class CompileServiceImpl<Compiler: CLICompiler<*>>(
alive = true alive = true
} }
private class IncrementalCompilationComponentsImpl(val targetToCache: Map<TargetId, CompileService.RemoteIncrementalCache>): IncrementalCompilationComponents {
// perf: cheap object, but still the pattern may be costly if there are too many calls to cache with the same id (which seems not to be the case now)
override fun getIncrementalCache(target: TargetId): IncrementalCache = RemoteIncrementalCacheClient(targetToCache[target]!!)
// TODO: add appropriate proxy into interaction when lookup tracker is needed
override fun getLookupTracker(): LookupTracker = LookupTracker.DO_NOTHING
}
private fun doCompile(args: Array<out String>, compilerMessagesStreamProxy: RemoteOutputStream, serviceOutputStreamProxy: RemoteOutputStream, body: (PrintStream) -> ExitCode): Int = private fun doCompile(args: Array<out String>, compilerMessagesStreamProxy: RemoteOutputStream, serviceOutputStreamProxy: RemoteOutputStream, body: (PrintStream) -> ExitCode): Int =
ifAlive { ifAlive {
val compilerMessagesStream = PrintStream(RemoteOutputStreamClient(compilerMessagesStreamProxy)) val compilerMessagesStream = PrintStream(RemoteOutputStreamClient(compilerMessagesStreamProxy))
@@ -145,14 +134,12 @@ class CompileServiceImpl<Compiler: CLICompiler<*>>(
} }
} }
private fun createCompileServices(incrementalCaches: Map<TargetId, CompileService.RemoteIncrementalCache>): Services = private fun createCompileServices(services: CompileService.RemoteCompilationServices): Services {
Services.Builder() val builder = Services.Builder()
.register(IncrementalCompilationComponents::class.java, IncrementalCompilationComponentsImpl(incrementalCaches)) services.incrementalCompilationComponents?.let { builder.register(IncrementalCompilationComponents::class.java, RemoteIncrementalCompilationComponentsClient(it)) }
// TODO: add remote proxy for cancellation status tracking services.compilationCanceledStatus?.let { builder.register(CompilationCanceledStatus::class.java, RemoteCompilationCanceledStatusClient(it)) }
// .register(javaClass<CompilationCanceledStatus>(), object: CompilationCanceledStatus { return builder.build()
// override fun checkCanceled(): Unit = if (context.getCancelStatus().isCanceled()) throw CompilationCanceledException() }
// })
.build()
fun usedMemory(): Long { fun usedMemory(): Long {
@@ -0,0 +1,27 @@
/*
* Copyright 2010-2015 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.rmi.service
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
import org.jetbrains.kotlin.rmi.CompileService
class RemoteCompilationCanceledStatusClient(val proxy: CompileService.RemoteCompilationCanceledStatus): CompilationCanceledStatus {
override fun checkCanceled() {
proxy.checkCanceled()
}
}
@@ -0,0 +1,31 @@
/*
* Copyright 2010-2015 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.rmi.service
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.rmi.CompileService
class RemoteIncrementalCompilationComponentsClient(val proxy: CompileService.RemoteIncrementalCompilationComponents) : IncrementalCompilationComponents {
override fun getIncrementalCache(target: TargetId): IncrementalCache = RemoteIncrementalCacheClient(proxy.getIncrementalCache(target))
override fun getLookupTracker(): LookupTracker = RemoteLookupTrackerClient(proxy.getLookupTracker())
}
@@ -0,0 +1,32 @@
/*
* Copyright 2010-2015 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.rmi.service
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.components.ScopeKind
import org.jetbrains.kotlin.rmi.CompileService
class RemoteLookupTrackerClient(val proxy: CompileService.RemoteLookupTracker) : LookupTracker {
private val isDoNothing = proxy.isDoNothing()
override fun record(lookupContainingFile: String, lookupLine: Int?, lookupColumn: Int?, scopeFqName: String, scopeKind: ScopeKind, name: String) {
if (!isDoNothing)
proxy.record(lookupContainingFile, lookupLine, lookupColumn, scopeFqName, scopeKind, name)
}
}
@@ -27,25 +27,23 @@ import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO
import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil
import org.jetbrains.kotlin.config.CompilerSettings import org.jetbrains.kotlin.config.CompilerSettings
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
import org.jetbrains.kotlin.modules.TargetId import org.jetbrains.kotlin.progress.CompilationCanceledStatus
import org.jetbrains.kotlin.rmi.* import org.jetbrains.kotlin.rmi.CompilerId
import org.jetbrains.kotlin.rmi.kotlinr.DaemonReportCategory import org.jetbrains.kotlin.rmi.configureDaemonJVMOptions
import org.jetbrains.kotlin.rmi.kotlinr.DaemonReportMessage import org.jetbrains.kotlin.rmi.configureDaemonOptions
import org.jetbrains.kotlin.rmi.kotlinr.DaemonReportingTargets import org.jetbrains.kotlin.rmi.isDaemonEnabled
import org.jetbrains.kotlin.rmi.kotlinr.KotlinCompilerClient import org.jetbrains.kotlin.rmi.kotlinr.*
import org.jetbrains.kotlin.utils.* import org.jetbrains.kotlin.utils.rethrow
import java.io.* import java.io.*
import java.lang.reflect.Field import java.lang.reflect.Field
import java.lang.reflect.Modifier import java.lang.reflect.Modifier
import java.util.ArrayList import java.util.*
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.INFO
public object KotlinCompilerRunner { public object KotlinCompilerRunner {
private val K2JVM_COMPILER = "org.jetbrains.kotlin.cli.jvm.K2JVMCompiler" private val K2JVM_COMPILER = "org.jetbrains.kotlin.cli.jvm.K2JVMCompiler"
@@ -58,14 +56,12 @@ public object KotlinCompilerRunner {
compilerSettings: CompilerSettings, compilerSettings: CompilerSettings,
messageCollector: MessageCollector, messageCollector: MessageCollector,
environment: CompilerEnvironment, environment: CompilerEnvironment,
incrementalCaches: Map<TargetId, IncrementalCache>?,
moduleFile: File, moduleFile: File,
collector: OutputItemsCollector) { collector: OutputItemsCollector) {
val arguments = mergeBeans(commonArguments, k2jvmArguments) val arguments = mergeBeans(commonArguments, k2jvmArguments)
setupK2JvmArguments(moduleFile, arguments) setupK2JvmArguments(moduleFile, arguments)
runCompiler(K2JVM_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment, runCompiler(K2JVM_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment)
incrementalCaches)
} }
public fun runK2JsCompiler( public fun runK2JsCompiler(
@@ -74,7 +70,6 @@ public object KotlinCompilerRunner {
compilerSettings: CompilerSettings, compilerSettings: CompilerSettings,
messageCollector: MessageCollector, messageCollector: MessageCollector,
environment: CompilerEnvironment, environment: CompilerEnvironment,
incrementalCaches: Map<TargetId, IncrementalCache>?,
collector: OutputItemsCollector, collector: OutputItemsCollector,
sourceFiles: Collection<File>, sourceFiles: Collection<File>,
libraryFiles: List<String>, libraryFiles: List<String>,
@@ -82,8 +77,7 @@ public object KotlinCompilerRunner {
val arguments = mergeBeans(commonArguments, k2jsArguments) val arguments = mergeBeans(commonArguments, k2jsArguments)
setupK2JsArguments(outputFile, sourceFiles, libraryFiles, arguments) setupK2JsArguments(outputFile, sourceFiles, libraryFiles, arguments)
runCompiler(K2JS_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment, runCompiler(K2JS_COMPILER, arguments, compilerSettings.additionalArguments, messageCollector, collector, environment)
incrementalCaches)
} }
private fun processCompilerOutput( private fun processCompilerOutput(
@@ -109,8 +103,7 @@ public object KotlinCompilerRunner {
additionalArguments: String, additionalArguments: String,
messageCollector: MessageCollector, messageCollector: MessageCollector,
collector: OutputItemsCollector, collector: OutputItemsCollector,
environment: CompilerEnvironment, environment: CompilerEnvironment) {
incrementalCaches: Map<TargetId, IncrementalCache>?) {
try { try {
messageCollector.report(INFO, "Using kotlin-home = " + environment.kotlinPaths.homePath, CompilerMessageLocation.NO_LOCATION) messageCollector.report(INFO, "Using kotlin-home = " + environment.kotlinPaths.homePath, CompilerMessageLocation.NO_LOCATION)
@@ -119,7 +112,7 @@ public object KotlinCompilerRunner {
val argsArray = argumentsList.toTypedArray() val argsArray = argumentsList.toTypedArray()
if (!tryCompileWithDaemon(messageCollector, collector, environment, incrementalCaches, argsArray)) { if (!tryCompileWithDaemon(messageCollector, collector, environment, argsArray)) {
// otherwise fallback to in-process // otherwise fallback to in-process
val stream = ByteArrayOutputStream() val stream = ByteArrayOutputStream()
@@ -139,14 +132,12 @@ public object KotlinCompilerRunner {
} }
private fun tryCompileWithDaemon( private fun tryCompileWithDaemon(messageCollector: MessageCollector,
messageCollector: MessageCollector, collector: OutputItemsCollector,
collector: OutputItemsCollector, environment: CompilerEnvironment,
environment: CompilerEnvironment, argsArray: Array<String>): Boolean {
incrementalCaches: Map<TargetId, IncrementalCache>?,
argsArray: Array<String>): Boolean {
if (incrementalCaches != null && isDaemonEnabled()) { if (isDaemonEnabled()) {
val libPath = CompilerRunnerUtil.getLibPath(environment.kotlinPaths, messageCollector) val libPath = CompilerRunnerUtil.getLibPath(environment.kotlinPaths, messageCollector)
// TODO: it may be a good idea to cache the compilerId, since making it means calculating digest over jar(s) and if \\ // TODO: it may be a good idea to cache the compilerId, since making it means calculating digest over jar(s) and if \\
// the lifetime of JPS process is small anyway, we can neglect the probability of changed compiler // the lifetime of JPS process is small anyway, we can neglect the probability of changed compiler
@@ -173,7 +164,11 @@ public object KotlinCompilerRunner {
val compilerOut = ByteArrayOutputStream() val compilerOut = ByteArrayOutputStream()
val daemonOut = ByteArrayOutputStream() val daemonOut = ByteArrayOutputStream()
val res = KotlinCompilerClient.incrementalCompile(daemon, argsArray, incrementalCaches, compilerOut, daemonOut) val services = CompilationServices(
incrementalCompilationComponents = environment.services.get(IncrementalCompilationComponents::class.java),
compilationCanceledStatus = environment.services.get(CompilationCanceledStatus::class.java))
val res = KotlinCompilerClient.incrementalCompile(daemon, argsArray, services, compilerOut, daemonOut)
processCompilerOutput(messageCollector, collector, compilerOut, res.toString()) processCompilerOutput(messageCollector, collector, compilerOut, res.toString())
BufferedReader(StringReader(daemonOut.toString())).forEachLine { BufferedReader(StringReader(daemonOut.toString())).forEachLine {
@@ -318,10 +318,7 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
) )
} }
return compileToJvm(allCompiledFiles, chunk, commonArguments, context, dirtyFilesHolder, environment, return compileToJvm(allCompiledFiles, chunk, commonArguments, context, dirtyFilesHolder, environment, filesToCompile, messageCollector)
incrementalCaches.mapKeysTo(HashMap<TargetId, IncrementalCache>(incrementalCaches.size()),
{ TargetId(it.getKey()) }),
filesToCompile, messageCollector)
} }
private fun createCompileEnvironment( private fun createCompileEnvironment(
@@ -519,7 +516,7 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
val compilerSettings = JpsKotlinCompilerSettings.getCompilerSettings(project) val compilerSettings = JpsKotlinCompilerSettings.getCompilerSettings(project)
val k2JsArguments = JpsKotlinCompilerSettings.getK2JsCompilerArguments(project) val k2JsArguments = JpsKotlinCompilerSettings.getK2JsCompilerArguments(project)
KotlinCompilerRunner.runK2JsCompiler(commonArguments, k2JsArguments, compilerSettings, messageCollector, environment, incrementalCaches, outputItemCollector, sourceFiles, libraryFiles, outputFile) KotlinCompilerRunner.runK2JsCompiler(commonArguments, k2JsArguments, compilerSettings, messageCollector, environment, outputItemCollector, sourceFiles, libraryFiles, outputFile)
return outputItemCollector return outputItemCollector
} }
@@ -542,7 +539,6 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
context: CompileContext, context: CompileContext,
dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>, dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>,
environment: CompilerEnvironment, environment: CompilerEnvironment,
incrementalCaches: MutableMap<TargetId, IncrementalCache>?,
filesToCompile: MultiMap<ModuleBuildTarget, File>, messageCollector: MessageCollectorAdapter filesToCompile: MultiMap<ModuleBuildTarget, File>, messageCollector: MessageCollectorAdapter
): OutputItemsCollectorImpl? { ): OutputItemsCollectorImpl? {
val outputItemCollector = OutputItemsCollectorImpl() val outputItemCollector = OutputItemsCollectorImpl()
@@ -586,7 +582,7 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
+ (if (totalRemovedFiles == 0) "" else " ($totalRemovedFiles removed files)") + (if (totalRemovedFiles == 0) "" else " ($totalRemovedFiles removed files)")
+ " in " + filesToCompile.keySet().map { it.getPresentableName() }.join()) + " in " + filesToCompile.keySet().map { it.getPresentableName() }.join())
KotlinCompilerRunner.runK2JvmCompiler(commonArguments, k2JvmArguments, compilerSettings, messageCollector, environment, incrementalCaches, moduleFile, outputItemCollector) KotlinCompilerRunner.runK2JvmCompiler(commonArguments, k2JvmArguments, compilerSettings, messageCollector, environment, moduleFile, outputItemCollector)
moduleFile.delete() moduleFile.delete()
return outputItemCollector return outputItemCollector