Implement server side IC
This commit is contained in:
+8
-8
@@ -93,7 +93,7 @@ abstract class KotlinCompilerRunner<in Env : CompilerEnvironment> {
|
|||||||
protected fun processCompilerOutput(
|
protected fun processCompilerOutput(
|
||||||
environment: Env,
|
environment: Env,
|
||||||
stream: ByteArrayOutputStream,
|
stream: ByteArrayOutputStream,
|
||||||
exitCode: ExitCode
|
exitCode: ExitCode?
|
||||||
) {
|
) {
|
||||||
val reader = BufferedReader(StringReader(stream.toString()))
|
val reader = BufferedReader(StringReader(stream.toString()))
|
||||||
CompilerOutputParser.parseCompilerMessagesFromReader(environment.messageCollector, reader, environment.outputItemsCollector)
|
CompilerOutputParser.parseCompilerMessagesFromReader(environment.messageCollector, reader, environment.outputItemsCollector)
|
||||||
@@ -194,12 +194,12 @@ abstract class KotlinCompilerRunner<in Env : CompilerEnvironment> {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun exitCodeFromProcessExitCode(res: Int): ExitCode =
|
protected fun exitCodeFromProcessExitCode(code: Int): ExitCode {
|
||||||
if (res == 0) {
|
val exitCode = ExitCode.values().find { it.code == code }
|
||||||
ExitCode.OK
|
if (exitCode != null) return exitCode
|
||||||
}
|
|
||||||
else {
|
log.debug("Could not find exit code by value: $code")
|
||||||
ExitCode.COMPILATION_ERROR
|
return if (code == 0) ExitCode.OK else ExitCode.COMPILATION_ERROR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
@@ -125,6 +125,16 @@ interface CompileService : Remote {
|
|||||||
operationsTracer: RemoteOperationsTracer?
|
operationsTracer: RemoteOperationsTracer?
|
||||||
): CallResult<Int>
|
): CallResult<Int>
|
||||||
|
|
||||||
|
@Throws(RemoteException::class)
|
||||||
|
fun serverSideJvmIC(
|
||||||
|
sessionId: Int,
|
||||||
|
args: Array<out String>,
|
||||||
|
servicesFacade: IncrementalCompilationServicesFacade,
|
||||||
|
compilerOutputStream: RemoteOutputStream,
|
||||||
|
serviceOutputStream: RemoteOutputStream,
|
||||||
|
operationsTracer: RemoteOperationsTracer?
|
||||||
|
): CallResult<Int>
|
||||||
|
|
||||||
@Throws(RemoteException::class)
|
@Throws(RemoteException::class)
|
||||||
fun leaseReplSession(
|
fun leaseReplSession(
|
||||||
aliveFlagPath: String?,
|
aliveFlagPath: String?,
|
||||||
|
|||||||
+56
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* 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.common
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
import java.rmi.Remote
|
||||||
|
import java.rmi.RemoteException
|
||||||
|
|
||||||
|
interface IncrementalCompilationServicesFacade : Remote {
|
||||||
|
@Throws(RemoteException::class)
|
||||||
|
fun areFileChangesKnown(): Boolean
|
||||||
|
|
||||||
|
@Throws(RemoteException::class)
|
||||||
|
fun modifiedFiles(): List<File>?
|
||||||
|
|
||||||
|
@Throws(RemoteException::class)
|
||||||
|
fun deletedFiles(): List<File>?
|
||||||
|
|
||||||
|
@Throws(RemoteException::class)
|
||||||
|
fun workingDir(): File
|
||||||
|
|
||||||
|
// ICReporter
|
||||||
|
|
||||||
|
@Throws(RemoteException::class)
|
||||||
|
fun shouldReportIC(): Boolean
|
||||||
|
|
||||||
|
@Throws(RemoteException::class)
|
||||||
|
fun reportIC(message: String)
|
||||||
|
|
||||||
|
@Throws(RemoteException::class)
|
||||||
|
fun reportCompileIteration(files: Iterable<File>, exitCode: Int)
|
||||||
|
|
||||||
|
// AnnotationFileUpdater
|
||||||
|
@Throws(RemoteException::class)
|
||||||
|
fun hasAnnotationsFileUpdater(): Boolean
|
||||||
|
|
||||||
|
@Throws(RemoteException::class)
|
||||||
|
fun updateAnnotations(outdatedClassesJvmNames: Iterable<String>)
|
||||||
|
|
||||||
|
@Throws(RemoteException::class)
|
||||||
|
fun revert()
|
||||||
|
}
|
||||||
@@ -12,5 +12,8 @@
|
|||||||
<orderEntry type="module" module-name="util" />
|
<orderEntry type="module" module-name="util" />
|
||||||
<orderEntry type="library" name="intellij-core" level="project" />
|
<orderEntry type="library" name="intellij-core" level="project" />
|
||||||
<orderEntry type="module" module-name="frontend" />
|
<orderEntry type="module" module-name="frontend" />
|
||||||
|
<orderEntry type="module" module-name="incremental-compilation-impl" />
|
||||||
|
<orderEntry type="module" module-name="build-common" />
|
||||||
|
<orderEntry type="module" module-name="descriptor.loader.java" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
@@ -20,20 +20,31 @@ import com.intellij.openapi.Disposable
|
|||||||
import com.intellij.openapi.util.Disposer
|
import com.intellij.openapi.util.Disposer
|
||||||
import com.intellij.openapi.vfs.impl.ZipHandler
|
import com.intellij.openapi.vfs.impl.ZipHandler
|
||||||
import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem
|
import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem
|
||||||
|
import org.jetbrains.kotlin.annotation.AnnotationFileUpdater
|
||||||
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.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY
|
import org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY
|
||||||
|
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||||
|
import org.jetbrains.kotlin.cli.common.messages.*
|
||||||
|
import org.jetbrains.kotlin.cli.common.modules.ModuleXmlParser
|
||||||
import org.jetbrains.kotlin.cli.common.repl.ReplCheckResult
|
import org.jetbrains.kotlin.cli.common.repl.ReplCheckResult
|
||||||
import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine
|
import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine
|
||||||
import org.jetbrains.kotlin.cli.common.repl.ReplCompileResult
|
import org.jetbrains.kotlin.cli.common.repl.ReplCompileResult
|
||||||
import org.jetbrains.kotlin.cli.common.repl.ReplEvalResult
|
import org.jetbrains.kotlin.cli.common.repl.ReplEvalResult
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
|
import org.jetbrains.kotlin.config.IncrementalCompilation
|
||||||
import org.jetbrains.kotlin.config.Services
|
import org.jetbrains.kotlin.config.Services
|
||||||
import org.jetbrains.kotlin.daemon.common.*
|
import org.jetbrains.kotlin.daemon.common.*
|
||||||
|
import org.jetbrains.kotlin.incremental.*
|
||||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||||
|
import org.jetbrains.kotlin.modules.Module
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||||
import java.io.BufferedOutputStream
|
import java.io.BufferedOutputStream
|
||||||
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.PrintStream
|
import java.io.PrintStream
|
||||||
import java.rmi.NoSuchObjectException
|
import java.rmi.NoSuchObjectException
|
||||||
@@ -306,6 +317,58 @@ class CompileServiceImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun serverSideJvmIC(
|
||||||
|
sessionId: Int,
|
||||||
|
args: Array<out String>,
|
||||||
|
servicesFacade: IncrementalCompilationServicesFacade,
|
||||||
|
compilerOutputStream: RemoteOutputStream,
|
||||||
|
serviceOutputStream: RemoteOutputStream,
|
||||||
|
operationsTracer: RemoteOperationsTracer?
|
||||||
|
): CompileService.CallResult<Int> {
|
||||||
|
return doCompile(sessionId, args, compilerOutputStream, serviceOutputStream, operationsTracer) { printStream, eventManager, profiler ->
|
||||||
|
val reporter = RemoteICReporter(servicesFacade)
|
||||||
|
val annotationFileUpdater = if (servicesFacade.hasAnnotationsFileUpdater()) RemoteAnnotationsFileUpdater(servicesFacade) else null
|
||||||
|
|
||||||
|
// these flags do not have any effect on the compiler (only on caches, incremental compilation logic, jps plugin)
|
||||||
|
// so it's OK to just set them true
|
||||||
|
IncrementalCompilation.setIsEnabled(true)
|
||||||
|
IncrementalCompilation.setIsExperimental(true)
|
||||||
|
|
||||||
|
val k2jvmArgs = K2JVMCompilerArguments()
|
||||||
|
(compiler[CompileService.TargetPlatform.JVM] as K2JVMCompiler).parseArguments(args, k2jvmArgs)
|
||||||
|
|
||||||
|
val moduleFile = k2jvmArgs.module?.let(::File)
|
||||||
|
assert(moduleFile?.exists() ?: false) { "Module does not exist ${k2jvmArgs.module}" }
|
||||||
|
val renderer = MessageRenderer.XML
|
||||||
|
val messageCollector = PrintingMessageCollector(printStream, renderer, k2jvmArgs.verbose)
|
||||||
|
val filteringMessageCollector = FilteringMessageCollector(messageCollector) { it == CompilerMessageSeverity.ERROR }
|
||||||
|
|
||||||
|
val parsedModule = ModuleXmlParser.parseModuleScript(k2jvmArgs.module, filteringMessageCollector)
|
||||||
|
val javaSourceRoots = parsedModule.modules.flatMapTo(HashSet()) { it.getJavaSourceRoots().map { File(it.path) } }
|
||||||
|
val allKotlinFiles = parsedModule.modules.flatMap { it.getSourceFiles().map(::File) }
|
||||||
|
k2jvmArgs.friendPaths = parsedModule.modules.flatMap(Module::getFriendPaths).toTypedArray()
|
||||||
|
|
||||||
|
val changedFiles = if (servicesFacade.areFileChangesKnown()) {
|
||||||
|
ChangedFiles.Known(servicesFacade.modifiedFiles()!!, servicesFacade.deletedFiles()!!)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ChangedFiles.Unknown()
|
||||||
|
}
|
||||||
|
|
||||||
|
val workingDir = servicesFacade.workingDir()
|
||||||
|
val versions = commonCacheVersions(workingDir) + standaloneCacheVersion(workingDir, forceEnable = true)
|
||||||
|
|
||||||
|
try {
|
||||||
|
printStream.print(renderer.renderPreamble())
|
||||||
|
IncrementalJvmCompilerRunner(workingDir, javaSourceRoots, versions, reporter, annotationFileUpdater)
|
||||||
|
.compile(allKotlinFiles, k2jvmArgs, messageCollector, { changedFiles })
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
printStream.print(renderer.renderConclusion())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun leaseReplSession(
|
override fun leaseReplSession(
|
||||||
aliveFlagPath: String?,
|
aliveFlagPath: String?,
|
||||||
targetPlatform: CompileService.TargetPlatform,
|
targetPlatform: CompileService.TargetPlatform,
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.annotation.AnnotationFileUpdater
|
||||||
|
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||||
|
import org.jetbrains.kotlin.daemon.common.IncrementalCompilationServicesFacade
|
||||||
|
import org.jetbrains.kotlin.incremental.ICReporter
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
internal class RemoteAnnotationsFileUpdater(private val servicesFacade: IncrementalCompilationServicesFacade) : AnnotationFileUpdater {
|
||||||
|
override fun updateAnnotations(outdatedClasses: Iterable<JvmClassName>) {
|
||||||
|
servicesFacade.updateAnnotations(outdatedClasses.map { it.internalName })
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun revert() {
|
||||||
|
servicesFacade.revert()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||||
|
import org.jetbrains.kotlin.daemon.common.IncrementalCompilationServicesFacade
|
||||||
|
import org.jetbrains.kotlin.incremental.ICReporter
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
internal class RemoteICReporter(private val servicesFacade: IncrementalCompilationServicesFacade) : ICReporter() {
|
||||||
|
override fun report(message: () -> String) {
|
||||||
|
if (servicesFacade.shouldReportIC()) {
|
||||||
|
servicesFacade.reportIC(message())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun reportCompileIteration(sourceFiles: Iterable<File>, exitCode: ExitCode) {
|
||||||
|
if (servicesFacade.shouldReportIC()) {
|
||||||
|
servicesFacade.reportCompileIteration(sourceFiles, exitCode.code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-7
@@ -49,10 +49,7 @@ fun makeIncrementally(
|
|||||||
messageCollector: MessageCollector = MessageCollector.NONE,
|
messageCollector: MessageCollector = MessageCollector.NONE,
|
||||||
reporter: ICReporter = EmptyICReporter
|
reporter: ICReporter = EmptyICReporter
|
||||||
) {
|
) {
|
||||||
val versions = listOf(normalCacheVersion(cachesDir),
|
val versions = commonCacheVersions(cachesDir) + standaloneCacheVersion(cachesDir)
|
||||||
experimentalCacheVersion(cachesDir),
|
|
||||||
dataContainerCacheVersion(cachesDir),
|
|
||||||
standaloneCacheVersion(cachesDir))
|
|
||||||
|
|
||||||
val kotlinExtensions = listOf("kt", "kts")
|
val kotlinExtensions = listOf("kt", "kts")
|
||||||
val allExtensions = kotlinExtensions + listOf("java")
|
val allExtensions = kotlinExtensions + listOf("java")
|
||||||
@@ -313,9 +310,6 @@ class IncrementalJvmCompilerRunner(
|
|||||||
caches.incrementalCache.removeClassfilesBySources(dirtySources)
|
caches.incrementalCache.removeClassfilesBySources(dirtySources)
|
||||||
|
|
||||||
val (sourcesToCompile, removedKotlinSources) = dirtySources.partition(File::exists)
|
val (sourcesToCompile, removedKotlinSources) = dirtySources.partition(File::exists)
|
||||||
if (sourcesToCompile.isNotEmpty()) {
|
|
||||||
reporter.report { "compile iteration: ${reporter.pathsAsString(sourcesToCompile)}" }
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo: more optimal to save only last iteration, but it will require adding standalone-ic specific logs
|
// todo: more optimal to save only last iteration, but it will require adding standalone-ic specific logs
|
||||||
// (because jps rebuilds all files from last build if it failed and gradle rebuilds everything)
|
// (because jps rebuilds all files from last build if it failed and gradle rebuilds everything)
|
||||||
|
|||||||
+7
-2
@@ -22,10 +22,15 @@ import java.io.File
|
|||||||
internal const val STANDALONE_CACHE_VERSION = 0
|
internal const val STANDALONE_CACHE_VERSION = 0
|
||||||
internal const val STANDALONE_VERSION_FILE_NAME = "standalone-ic-format-version.txt"
|
internal const val STANDALONE_VERSION_FILE_NAME = "standalone-ic-format-version.txt"
|
||||||
|
|
||||||
internal fun standaloneCacheVersion(dataRoot: File): CacheVersion =
|
fun standaloneCacheVersion(dataRoot: File, forceEnable: Boolean = false): CacheVersion =
|
||||||
CacheVersion(ownVersion = STANDALONE_CACHE_VERSION,
|
CacheVersion(ownVersion = STANDALONE_CACHE_VERSION,
|
||||||
versionFile = File(dataRoot, STANDALONE_VERSION_FILE_NAME),
|
versionFile = File(dataRoot, STANDALONE_VERSION_FILE_NAME),
|
||||||
whenVersionChanged = CacheVersion.Action.REBUILD_ALL_KOTLIN,
|
whenVersionChanged = CacheVersion.Action.REBUILD_ALL_KOTLIN,
|
||||||
whenTurnedOn = CacheVersion.Action.REBUILD_ALL_KOTLIN,
|
whenTurnedOn = CacheVersion.Action.REBUILD_ALL_KOTLIN,
|
||||||
whenTurnedOff = CacheVersion.Action.REBUILD_ALL_KOTLIN,
|
whenTurnedOff = CacheVersion.Action.REBUILD_ALL_KOTLIN,
|
||||||
isEnabled = { IncrementalCompilation.isExperimental() })
|
isEnabled = { IncrementalCompilation.isExperimental() || forceEnable })
|
||||||
|
|
||||||
|
fun commonCacheVersions(cachesDir: File): List<CacheVersion> =
|
||||||
|
listOf(normalCacheVersion(cachesDir),
|
||||||
|
experimentalCacheVersion(cachesDir),
|
||||||
|
dataContainerCacheVersion(cachesDir))
|
||||||
+14
-1
@@ -1,11 +1,14 @@
|
|||||||
package org.jetbrains.kotlin.compilerRunner
|
package org.jetbrains.kotlin.compilerRunner
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.annotation.AnnotationFileUpdater
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||||
import org.jetbrains.kotlin.config.Services
|
import org.jetbrains.kotlin.config.Services
|
||||||
|
import org.jetbrains.kotlin.incremental.ChangedFiles
|
||||||
|
import org.jetbrains.kotlin.incremental.GradleICReporter
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
|
||||||
internal class GradleCompilerEnvironment(
|
internal open class GradleCompilerEnvironment(
|
||||||
val compilerJar: File,
|
val compilerJar: File,
|
||||||
messageCollector: MessageCollector,
|
messageCollector: MessageCollector,
|
||||||
outputItemsCollector: OutputItemsCollector
|
outputItemsCollector: OutputItemsCollector
|
||||||
@@ -16,3 +19,13 @@ internal class GradleCompilerEnvironment(
|
|||||||
val compilerClasspathURLs: List<URL>
|
val compilerClasspathURLs: List<URL>
|
||||||
get() = compilerClasspath.map { it.toURI().toURL() }
|
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.ExitCode
|
||||||
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
|
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.CompilerMessageSeverity
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||||
import org.jetbrains.kotlin.config.Services
|
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.ParentLastURLClassLoader
|
||||||
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
|
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
|
||||||
|
import org.jetbrains.kotlin.incremental.ChangedFiles
|
||||||
import org.jetbrains.kotlin.incremental.classpathAsList
|
import org.jetbrains.kotlin.incremental.classpathAsList
|
||||||
import org.jetbrains.kotlin.incremental.destinationAsFile
|
import org.jetbrains.kotlin.incremental.destinationAsFile
|
||||||
import org.jetbrains.kotlin.incremental.makeModuleFile
|
import org.jetbrains.kotlin.incremental.makeModuleFile
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.*
|
||||||
import java.io.File
|
import java.rmi.server.UnicastRemoteObject
|
||||||
import java.io.PrintStream
|
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
internal const val KOTLIN_COMPILER_EXECUTION_STRATEGY_PROPERTY = "kotlin.compiler.execution.strategy"
|
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
|
environment: GradleCompilerEnvironment
|
||||||
): ExitCode {
|
): ExitCode {
|
||||||
val outputDir = args.destinationAsFile
|
val outputDir = args.destinationAsFile
|
||||||
log.debug("Removing all kotlin classes in $outputDir")
|
|
||||||
log.info("Using kotlin compiler jar: ${environment.compilerJar}")
|
log.info("Using kotlin compiler jar: ${environment.compilerJar}")
|
||||||
|
|
||||||
// we're free to delete all classes since only we know about that directory
|
if (environment !is GradleIncrementalCompilerEnvironment) {
|
||||||
outputDir.deleteRecursively()
|
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(
|
val moduleFile = makeModuleFile(
|
||||||
args.moduleName,
|
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? {
|
override fun compileWithDaemon(compilerClassName: String, argsArray: Array<String>, environment: GradleCompilerEnvironment): ExitCode? {
|
||||||
val exitCode = super.compileWithDaemon(compilerClassName, argsArray, environment, retryOnConnectionError)
|
val exitCode = if (environment is GradleIncrementalCompilerEnvironment) {
|
||||||
|
performIncrementalCompilationWithDaemon(argsArray, environment)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
super.compileWithDaemon(compilerClassName, argsArray, environment)
|
||||||
|
}
|
||||||
exitCode?.let {
|
exitCode?.let {
|
||||||
logFinish(DAEMON_EXECUTION_STRATEGY)
|
logFinish(DAEMON_EXECUTION_STRATEGY)
|
||||||
}
|
}
|
||||||
return exitCode
|
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(
|
private fun compileOutOfProcess(
|
||||||
argsArray: Array<String>,
|
argsArray: Array<String>,
|
||||||
compilerClassName: 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.common.messages.MessageCollector
|
||||||
import org.jetbrains.kotlin.cli.js.K2JSCompiler
|
import org.jetbrains.kotlin.cli.js.K2JSCompiler
|
||||||
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
||||||
import org.jetbrains.kotlin.compilerRunner.ArgumentUtils
|
import org.jetbrains.kotlin.compilerRunner.*
|
||||||
import org.jetbrains.kotlin.compilerRunner.GradleCompilerEnvironment
|
|
||||||
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner
|
|
||||||
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
|
|
||||||
import org.jetbrains.kotlin.gradle.dsl.*
|
import org.jetbrains.kotlin.gradle.dsl.*
|
||||||
import org.jetbrains.kotlin.gradle.plugin.CoroutineSupport
|
import org.jetbrains.kotlin.gradle.plugin.CoroutineSupport
|
||||||
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
|
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
|
||||||
@@ -206,36 +203,27 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
|
|||||||
args.classpathAsList = compileClasspath.toList()
|
args.classpathAsList = compileClasspath.toList()
|
||||||
args.destinationAsFile = destinationDir
|
args.destinationAsFile = destinationDir
|
||||||
val outputItemCollector = OutputItemsCollectorImpl()
|
val outputItemCollector = OutputItemsCollectorImpl()
|
||||||
|
val compilerRunner = GradleCompilerRunner(project)
|
||||||
|
|
||||||
if (!incremental) {
|
val environment = when {
|
||||||
anyClassesCompiled = true
|
!incremental -> GradleCompilerEnvironment(compilerJar, messageCollector, outputItemCollector)
|
||||||
val compilerRunner = GradleCompilerRunner(project)
|
else -> {
|
||||||
val environment = GradleCompilerEnvironment(compilerJar, messageCollector, outputItemCollector)
|
logger.warn(USING_EXPERIMENTAL_INCREMENTAL_MESSAGE)
|
||||||
val exitCode = compilerRunner.runJvmCompiler(sourceRoots.kotlinSourceFiles, sourceRoots.javaSourceRoots, args, environment)
|
val reporter = GradleICReporter(project.rootProject.projectDir)
|
||||||
processCompilerExitCode(exitCode)
|
GradleIncrementalCompilerEnvironment(compilerJar, changedFiles, reporter, taskBuildDirectory,
|
||||||
return
|
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 {
|
try {
|
||||||
val exitCode = compiler.compile(sourceRoots.kotlinSourceFiles, args, messageCollector, { changedFiles })
|
val exitCode = compilerRunner.runJvmCompiler(sourceRoots.kotlinSourceFiles, sourceRoots.javaSourceRoots, args, environment)
|
||||||
processCompilerExitCode(exitCode)
|
processCompilerExitCode(exitCode)
|
||||||
}
|
}
|
||||||
catch (e: Throwable) {
|
catch (e: Throwable) {
|
||||||
cleanupOnError()
|
cleanupOnError()
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
anyClassesCompiled = compiler.anyClassesCompiled
|
anyClassesCompiled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun cleanupOnError() {
|
private fun cleanupOnError() {
|
||||||
|
|||||||
+11
@@ -17,17 +17,28 @@
|
|||||||
package org.jetbrains.kotlin.incremental
|
package org.jetbrains.kotlin.incremental
|
||||||
|
|
||||||
import org.gradle.api.logging.Logging
|
import org.gradle.api.logging.Logging
|
||||||
|
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||||
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
|
import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
internal class GradleICReporter(private val projectRootFile: File) : ICReporter() {
|
internal class GradleICReporter(private val projectRootFile: File) : ICReporter() {
|
||||||
private val log = Logging.getLogger(GradleICReporter::class.java)
|
private val log = Logging.getLogger(GradleICReporter::class.java)
|
||||||
|
|
||||||
|
val isDebugEnabled: Boolean
|
||||||
|
get() = log.isDebugEnabled
|
||||||
|
|
||||||
override fun report(message: ()->String) {
|
override fun report(message: ()->String) {
|
||||||
log.kotlinDebug(message)
|
log.kotlinDebug(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun pathsAsString(files: Iterable<File>): String =
|
override fun pathsAsString(files: Iterable<File>): String =
|
||||||
files.pathsAsStringRelativeTo(projectRootFile)
|
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