Fix multiproject Gradle IC with daemon

This commit is contained in:
Alexey Tsvetkov
2016-12-06 17:34:43 +03:00
parent fb869277d9
commit 8228d5828e
14 changed files with 235 additions and 45 deletions
@@ -1,10 +1,13 @@
package org.jetbrains.kotlin.compilerRunner
import org.gradle.api.internal.artifacts.dsl.ArtifactFile
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 org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistry
import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProvider
import java.io.File
import java.net.URL
@@ -27,5 +30,7 @@ internal class GradleIncrementalCompilerEnvironment(
val workingDir: File,
messageCollector: MessageCollector,
outputItemsCollector: OutputItemsCollector,
val kaptAnnotationsFileUpdater: AnnotationFileUpdater?
val kaptAnnotationsFileUpdater: AnnotationFileUpdater?,
val artifactDifferenceRegistryProvider: ArtifactDifferenceRegistryProvider?,
val artifactFile: File?
) : GradleCompilerEnvironment(compilerJar, messageCollector, outputItemsCollector)
@@ -20,7 +20,12 @@ 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.daemon.common.SimpleDirtyData
import org.jetbrains.kotlin.daemon.incremental.toDirtyData
import org.jetbrains.kotlin.daemon.incremental.toSimpleDirtyData
import org.jetbrains.kotlin.incremental.ChangedFiles
import org.jetbrains.kotlin.incremental.DirtyData
import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifference
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import java.io.File
import java.rmi.server.UnicastRemoteObject
@@ -71,4 +76,32 @@ internal class IncrementalCompilationFacadeImpl(
val jvmNames = outdatedClassesJvmNames.map { JvmClassName.byInternalName(it) }
environment.kaptAnnotationsFileUpdater!!.updateAnnotations(jvmNames)
}
override fun getChanges(artifact: File, sinceTS: Long): Iterable<SimpleDirtyData>? {
val artifactChanges = environment.artifactDifferenceRegistryProvider?.withRegistry(environment.reporter) { registry ->
registry[artifact]
} ?: return null
val (beforeLastBuild, afterLastBuild) = artifactChanges.partition { it.buildTS < sinceTS }
if (beforeLastBuild.isEmpty()) return null
return afterLastBuild.map { it.dirtyData.toSimpleDirtyData() }
}
override fun registerChanges(timestamp: Long, dirtyData: SimpleDirtyData) {
val artifactFile = environment.artifactFile ?: return
environment.artifactDifferenceRegistryProvider?.withRegistry(environment.reporter) { registry ->
registry.add(artifactFile, ArtifactDifference(timestamp, dirtyData.toDirtyData()))
}
}
override fun unknownChanges(timestamp: Long) {
val artifactFile = environment.artifactFile ?: return
environment.artifactDifferenceRegistryProvider?.withRegistry(environment.reporter) { registry ->
registry.remove(artifactFile)
registry.add(artifactFile, ArtifactDifference(timestamp, DirtyData()))
}
}
}
@@ -45,6 +45,7 @@ import org.jetbrains.kotlin.gradle.plugin.kotlinDebug
import org.jetbrains.kotlin.gradle.plugin.kotlinInfo
import org.jetbrains.kotlin.gradle.utils.ParsedGradleVersion
import org.jetbrains.kotlin.incremental.*
import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistry
import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProvider
import org.jetbrains.kotlin.utils.LibraryUtils
import java.io.File
@@ -204,25 +205,34 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
args.destinationAsFile = destinationDir
val outputItemCollector = OutputItemsCollectorImpl()
val compilerRunner = GradleCompilerRunner(project)
val reporter = GradleICReporter(project.rootProject.projectDir)
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)
messageCollector, outputItemCollector, kaptAnnotationsFileUpdater,
artifactDifferenceRegistryProvider,
artifactFile)
}
}
try {
val exitCode = compilerRunner.runJvmCompiler(sourceRoots.kotlinSourceFiles, sourceRoots.javaSourceRoots, args, environment)
processCompilerExitCode(exitCode)
artifactDifferenceRegistryProvider?.withRegistry(reporter) {
it.flush(true)
}
}
catch (e: Throwable) {
cleanupOnError()
artifactDifferenceRegistryProvider?.clean()
throw e
}
finally {
artifactDifferenceRegistryProvider?.withRegistry(reporter, ArtifactDifferenceRegistry::close)
}
anyClassesCompiled = true
}
@@ -0,0 +1,47 @@
/*
* 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.incremental.multiproject
import org.jetbrains.kotlin.incremental.DirtyData
import org.jetbrains.kotlin.incremental.ICReporter
import java.io.File
interface ArtifactDifferenceRegistry {
operator fun get(artifact: File): Iterable<ArtifactDifference>?
fun add(artifact: File, difference: ArtifactDifference)
fun remove(artifact: File)
fun flush(memoryCachesOnly: Boolean)
fun close()
}
class ArtifactDifference(val buildTS: Long, val dirtyData: DirtyData)
interface ArtifactDifferenceRegistryProvider {
fun <T> withRegistry(
report: (String) -> Unit,
fn: (ArtifactDifferenceRegistry) -> T
): T?
fun <T> withRegistry(
reporter: ICReporter,
fn: (ArtifactDifferenceRegistry) -> T
): T? {
return withRegistry({reporter.report {it}}, fn)
}
fun clean()
}