Implement server side IC
This commit is contained in:
+15
-2
@@ -1,11 +1,14 @@
|
||||
package org.jetbrains.kotlin.compilerRunner
|
||||
|
||||
import org.jetbrains.kotlin.annotation.AnnotationFileUpdater
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.config.Services
|
||||
import org.jetbrains.kotlin.incremental.ChangedFiles
|
||||
import org.jetbrains.kotlin.incremental.GradleICReporter
|
||||
import java.io.File
|
||||
import java.net.URL
|
||||
|
||||
internal class GradleCompilerEnvironment(
|
||||
internal open class GradleCompilerEnvironment(
|
||||
val compilerJar: File,
|
||||
messageCollector: MessageCollector,
|
||||
outputItemsCollector: OutputItemsCollector
|
||||
@@ -15,4 +18,14 @@ internal class GradleCompilerEnvironment(
|
||||
|
||||
val compilerClasspathURLs: List<URL>
|
||||
get() = compilerClasspath.map { it.toURI().toURL() }
|
||||
}
|
||||
}
|
||||
|
||||
internal class GradleIncrementalCompilerEnvironment(
|
||||
compilerJar: File,
|
||||
val changedFiles: ChangedFiles,
|
||||
val reporter: GradleICReporter,
|
||||
val workingDir: File,
|
||||
messageCollector: MessageCollector,
|
||||
outputItemsCollector: OutputItemsCollector,
|
||||
val kaptAnnotationsFileUpdater: AnnotationFileUpdater?
|
||||
) : GradleCompilerEnvironment(compilerJar, messageCollector, outputItemsCollector)
|
||||
+45
-8
@@ -22,16 +22,22 @@ import org.gradle.api.Project
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.config.Services
|
||||
import org.jetbrains.kotlin.daemon.client.RemoteOutputStreamServer
|
||||
import org.jetbrains.kotlin.daemon.common.IncrementalCompilationServicesFacade
|
||||
import org.jetbrains.kotlin.daemon.common.LoopbackNetworkInterface
|
||||
import org.jetbrains.kotlin.daemon.common.SOCKET_ANY_FREE_PORT
|
||||
import org.jetbrains.kotlin.gradle.plugin.ParentLastURLClassLoader
|
||||
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
|
||||
import org.jetbrains.kotlin.incremental.ChangedFiles
|
||||
import org.jetbrains.kotlin.incremental.classpathAsList
|
||||
import org.jetbrains.kotlin.incremental.destinationAsFile
|
||||
import org.jetbrains.kotlin.incremental.makeModuleFile
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.File
|
||||
import java.io.PrintStream
|
||||
import java.io.*
|
||||
import java.rmi.server.UnicastRemoteObject
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
internal const val KOTLIN_COMPILER_EXECUTION_STRATEGY_PROPERTY = "kotlin.compiler.execution.strategy"
|
||||
@@ -58,11 +64,13 @@ internal class GradleCompilerRunner(private val project: Project) : KotlinCompil
|
||||
environment: GradleCompilerEnvironment
|
||||
): ExitCode {
|
||||
val outputDir = args.destinationAsFile
|
||||
log.debug("Removing all kotlin classes in $outputDir")
|
||||
log.info("Using kotlin compiler jar: ${environment.compilerJar}")
|
||||
|
||||
// we're free to delete all classes since only we know about that directory
|
||||
outputDir.deleteRecursively()
|
||||
if (environment !is GradleIncrementalCompilerEnvironment) {
|
||||
log.debug("Removing all kotlin classes in $outputDir")
|
||||
// we're free to delete all classes since only we know about that directory
|
||||
outputDir.deleteRecursively()
|
||||
}
|
||||
|
||||
val moduleFile = makeModuleFile(
|
||||
args.moduleName,
|
||||
@@ -121,14 +129,43 @@ internal class GradleCompilerRunner(private val project: Project) : KotlinCompil
|
||||
}
|
||||
}
|
||||
|
||||
override fun compileWithDaemon(compilerClassName: String, argsArray: Array<String>, environment: GradleCompilerEnvironment, retryOnConnectionError: Boolean): ExitCode? {
|
||||
val exitCode = super.compileWithDaemon(compilerClassName, argsArray, environment, retryOnConnectionError)
|
||||
override fun compileWithDaemon(compilerClassName: String, argsArray: Array<String>, environment: GradleCompilerEnvironment): ExitCode? {
|
||||
val exitCode = if (environment is GradleIncrementalCompilerEnvironment) {
|
||||
performIncrementalCompilationWithDaemon(argsArray, environment)
|
||||
}
|
||||
else {
|
||||
super.compileWithDaemon(compilerClassName, argsArray, environment)
|
||||
}
|
||||
exitCode?.let {
|
||||
logFinish(DAEMON_EXECUTION_STRATEGY)
|
||||
}
|
||||
return exitCode
|
||||
}
|
||||
|
||||
private fun performIncrementalCompilationWithDaemon(argsArray: Array<String>, environment: GradleIncrementalCompilerEnvironment): ExitCode? {
|
||||
val port = SOCKET_ANY_FREE_PORT
|
||||
val services = IncrementalCompilationFacadeImpl(environment, port)
|
||||
val compilerOut = ByteArrayOutputStream()
|
||||
val daemonOut = ByteArrayOutputStream()
|
||||
|
||||
val res = withDaemon(environment) { daemon, sessionId ->
|
||||
val remoteCompilerOut = RemoteOutputStreamServer(compilerOut, port)
|
||||
val remoteDaemonOut = RemoteOutputStreamServer(daemonOut, port)
|
||||
daemon.serverSideJvmIC(sessionId, argsArray, services, remoteCompilerOut, remoteDaemonOut, null)
|
||||
}
|
||||
|
||||
val exitCode = res?.get()?.let { exitCodeFromProcessExitCode(it) }
|
||||
if (exitCode == null) {
|
||||
log.warn("Could not perform incremental compilation with Kotlin compile daemon, " +
|
||||
"non-incremental compilation in fallback mode will be performed")
|
||||
}
|
||||
processCompilerOutput(environment, compilerOut, exitCode)
|
||||
BufferedReader(StringReader(daemonOut.toString())).forEachLine {
|
||||
environment.messageCollector.report(CompilerMessageSeverity.INFO, it, CompilerMessageLocation.NO_LOCATION)
|
||||
}
|
||||
return exitCode
|
||||
}
|
||||
|
||||
private fun compileOutOfProcess(
|
||||
argsArray: Array<String>,
|
||||
compilerClassName: String,
|
||||
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.compilerRunner
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
import org.jetbrains.kotlin.daemon.common.IncrementalCompilationServicesFacade
|
||||
import org.jetbrains.kotlin.daemon.common.LoopbackNetworkInterface
|
||||
import org.jetbrains.kotlin.daemon.common.SOCKET_ANY_FREE_PORT
|
||||
import org.jetbrains.kotlin.incremental.ChangedFiles
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import java.io.File
|
||||
import java.rmi.server.UnicastRemoteObject
|
||||
|
||||
internal class IncrementalCompilationFacadeImpl(
|
||||
private val environment: GradleIncrementalCompilerEnvironment,
|
||||
port: Int = SOCKET_ANY_FREE_PORT
|
||||
) : IncrementalCompilationServicesFacade,
|
||||
UnicastRemoteObject(port, LoopbackNetworkInterface.clientLoopbackSocketFactory, LoopbackNetworkInterface.serverLoopbackSocketFactory) {
|
||||
|
||||
override fun areFileChangesKnown(): Boolean {
|
||||
return environment.changedFiles is ChangedFiles.Known
|
||||
}
|
||||
|
||||
override fun deletedFiles(): List<File> {
|
||||
return (environment.changedFiles as ChangedFiles.Known).removed
|
||||
}
|
||||
|
||||
override fun modifiedFiles(): List<File> {
|
||||
return (environment.changedFiles as ChangedFiles.Known).modified
|
||||
}
|
||||
|
||||
override fun reportCompileIteration(files: Iterable<File>, exitCode: Int) {
|
||||
environment.reporter.reportCompileIteration(files, ExitCode.values().first { it.code == exitCode })
|
||||
}
|
||||
|
||||
override fun reportIC(message: String) {
|
||||
environment.reporter.report { message }
|
||||
}
|
||||
|
||||
override fun shouldReportIC(): Boolean {
|
||||
return environment.reporter.isDebugEnabled
|
||||
}
|
||||
|
||||
override fun workingDir(): File {
|
||||
return environment.workingDir
|
||||
}
|
||||
|
||||
override fun hasAnnotationsFileUpdater(): Boolean {
|
||||
return environment.kaptAnnotationsFileUpdater != null
|
||||
}
|
||||
|
||||
override fun revert() {
|
||||
environment.kaptAnnotationsFileUpdater!!.revert()
|
||||
}
|
||||
|
||||
override fun updateAnnotations(outdatedClassesJvmNames: Iterable<String>) {
|
||||
val jvmNames = outdatedClassesJvmNames.map { JvmClassName.byInternalName(it) }
|
||||
environment.kaptAnnotationsFileUpdater!!.updateAnnotations(jvmNames)
|
||||
}
|
||||
}
|
||||
+12
-24
@@ -38,10 +38,7 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.cli.js.K2JSCompiler
|
||||
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
||||
import org.jetbrains.kotlin.compilerRunner.ArgumentUtils
|
||||
import org.jetbrains.kotlin.compilerRunner.GradleCompilerEnvironment
|
||||
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner
|
||||
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
|
||||
import org.jetbrains.kotlin.compilerRunner.*
|
||||
import org.jetbrains.kotlin.gradle.dsl.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.CoroutineSupport
|
||||
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
|
||||
@@ -206,36 +203,27 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
|
||||
args.classpathAsList = compileClasspath.toList()
|
||||
args.destinationAsFile = destinationDir
|
||||
val outputItemCollector = OutputItemsCollectorImpl()
|
||||
val compilerRunner = GradleCompilerRunner(project)
|
||||
|
||||
if (!incremental) {
|
||||
anyClassesCompiled = true
|
||||
val compilerRunner = GradleCompilerRunner(project)
|
||||
val environment = GradleCompilerEnvironment(compilerJar, messageCollector, outputItemCollector)
|
||||
val exitCode = compilerRunner.runJvmCompiler(sourceRoots.kotlinSourceFiles, sourceRoots.javaSourceRoots, args, environment)
|
||||
processCompilerExitCode(exitCode)
|
||||
return
|
||||
val environment = when {
|
||||
!incremental -> GradleCompilerEnvironment(compilerJar, messageCollector, outputItemCollector)
|
||||
else -> {
|
||||
logger.warn(USING_EXPERIMENTAL_INCREMENTAL_MESSAGE)
|
||||
val reporter = GradleICReporter(project.rootProject.projectDir)
|
||||
GradleIncrementalCompilerEnvironment(compilerJar, changedFiles, reporter, taskBuildDirectory,
|
||||
messageCollector, outputItemCollector, kaptAnnotationsFileUpdater)
|
||||
}
|
||||
}
|
||||
|
||||
logger.warn(USING_EXPERIMENTAL_INCREMENTAL_MESSAGE)
|
||||
val reporter = GradleICReporter(project.rootProject.projectDir)
|
||||
val compiler = IncrementalJvmCompilerRunner(
|
||||
taskBuildDirectory,
|
||||
sourceRoots.javaSourceRoots,
|
||||
cacheVersions,
|
||||
reporter,
|
||||
kaptAnnotationsFileUpdater,
|
||||
artifactDifferenceRegistryProvider,
|
||||
artifactFile
|
||||
)
|
||||
try {
|
||||
val exitCode = compiler.compile(sourceRoots.kotlinSourceFiles, args, messageCollector, { changedFiles })
|
||||
val exitCode = compilerRunner.runJvmCompiler(sourceRoots.kotlinSourceFiles, sourceRoots.javaSourceRoots, args, environment)
|
||||
processCompilerExitCode(exitCode)
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
cleanupOnError()
|
||||
throw e
|
||||
}
|
||||
anyClassesCompiled = compiler.anyClassesCompiled
|
||||
anyClassesCompiled = true
|
||||
}
|
||||
|
||||
private fun cleanupOnError() {
|
||||
|
||||
+11
@@ -17,17 +17,28 @@
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import org.gradle.api.logging.Logging
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
|
||||
import java.io.File
|
||||
|
||||
internal class GradleICReporter(private val projectRootFile: File) : ICReporter() {
|
||||
private val log = Logging.getLogger(GradleICReporter::class.java)
|
||||
|
||||
val isDebugEnabled: Boolean
|
||||
get() = log.isDebugEnabled
|
||||
|
||||
override fun report(message: ()->String) {
|
||||
log.kotlinDebug(message)
|
||||
}
|
||||
|
||||
override fun pathsAsString(files: Iterable<File>): String =
|
||||
files.pathsAsStringRelativeTo(projectRootFile)
|
||||
|
||||
override fun reportCompileIteration(sourceFiles: Iterable<File>, exitCode: ExitCode) {
|
||||
if (sourceFiles.any()) {
|
||||
report { "compile iteration: ${pathsAsString(sourceFiles)}" }
|
||||
}
|
||||
report { "compiler exit code: $exitCode" }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user