Gradle: compile tests incrementally when main is changed
#KT-17674 fixed
This commit is contained in:
+3
-1
@@ -48,7 +48,9 @@ class IncrementalCompilationOptions(
|
||||
/** @See [ReportSeverity] */
|
||||
reportSeverity: Int,
|
||||
/** @See [CompilationResultCategory]] */
|
||||
requestedCompilationResults: Array<Int>
|
||||
requestedCompilationResults: Array<Int>,
|
||||
val resultDifferenceFile: File? = null,
|
||||
val friendDifferenceFile: File? = null
|
||||
) : CompilationOptions(compilerMode, targetPlatform, reportCategories, reportSeverity, requestedCompilationResults) {
|
||||
companion object {
|
||||
const val serialVersionUID: Long = 0
|
||||
|
||||
@@ -507,9 +507,12 @@ class CompileServiceImpl(
|
||||
workingDir,
|
||||
enabled = true)
|
||||
|
||||
return IncrementalJvmCompilerRunner(workingDir, javaSourceRoots, versions, reporter, annotationFileUpdater,
|
||||
artifactChanges, changesRegistry)
|
||||
.compile(allKotlinFiles, k2jvmArgs, compilerMessageCollector, { changedFiles })
|
||||
val compiler = IncrementalJvmCompilerRunner(workingDir, javaSourceRoots, versions,
|
||||
reporter, annotationFileUpdater,
|
||||
artifactChanges, changesRegistry,
|
||||
buildHistoryFile = incrementalCompilationOptions.resultDifferenceFile,
|
||||
friendBuildHistoryFile = incrementalCompilationOptions.friendDifferenceFile)
|
||||
return compiler.compile(allKotlinFiles, k2jvmArgs, compilerMessageCollector, { changedFiles })
|
||||
}
|
||||
|
||||
override fun leaseReplSession(
|
||||
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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
|
||||
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.io.ObjectInputStream
|
||||
import java.io.ObjectOutputStream
|
||||
|
||||
data class BuildDifference(val ts: Long, val isIncremental: Boolean, val dirtyData: DirtyData)
|
||||
|
||||
// todo: storage format can be optimized by compressing fq-names
|
||||
data class BuildDiffsStorage(val buildDiffs: List<BuildDifference>) {
|
||||
companion object {
|
||||
fun readFromFile(file: File, reporter: ICReporter?): BuildDiffsStorage? {
|
||||
fun reportFail(reason: String) {
|
||||
reporter?.report { "Could not read diff from file $file: $reason" }
|
||||
}
|
||||
|
||||
if (!file.exists()) return null
|
||||
|
||||
try {
|
||||
ObjectInputStream(file.inputStream().buffered()).use { input ->
|
||||
val version = input.readInt()
|
||||
if (version != CURRENT_VERSION) {
|
||||
reportFail("incompatible version $version, actual version is $CURRENT_VERSION")
|
||||
return null
|
||||
}
|
||||
|
||||
val size = input.readInt()
|
||||
val result = ArrayList<BuildDifference>(size)
|
||||
repeat(size) {
|
||||
result.add(input.readBuildDifference())
|
||||
}
|
||||
return BuildDiffsStorage(result)
|
||||
}
|
||||
}
|
||||
catch (e: IOException) {
|
||||
reportFail(e.toString())
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
fun writeToFile(file: File, storage: BuildDiffsStorage, reporter: ICReporter?) {
|
||||
file.parentFile.mkdirs()
|
||||
|
||||
try {
|
||||
ObjectOutputStream(file.outputStream().buffered()).use { output ->
|
||||
output.writeInt(CURRENT_VERSION)
|
||||
|
||||
val diffsToWrite = storage.buildDiffs.sortedBy { it.ts }.takeLast(MAX_DIFFS_ENTRIES)
|
||||
output.writeInt(diffsToWrite.size)
|
||||
for (diff in diffsToWrite) {
|
||||
output.writeBuildDifference(diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e: IOException) {
|
||||
reporter?.report { "Could not write diff to file $file: $e" }
|
||||
}
|
||||
}
|
||||
|
||||
private fun ObjectInputStream.readBuildDifference(): BuildDifference {
|
||||
val ts = readLong()
|
||||
val isIncremental = readBoolean()
|
||||
val dirtyData = readDirtyData()
|
||||
return BuildDifference(ts, isIncremental, dirtyData)
|
||||
}
|
||||
|
||||
private fun ObjectOutputStream.writeBuildDifference(diff: BuildDifference) {
|
||||
writeLong(diff.ts)
|
||||
writeBoolean(diff.isIncremental)
|
||||
writeDirtyData(diff.dirtyData)
|
||||
}
|
||||
|
||||
private fun ObjectInputStream.readDirtyData(): DirtyData {
|
||||
val lookupSymbolSize = readInt()
|
||||
val lookupSymbols = ArrayList<LookupSymbol>(lookupSymbolSize)
|
||||
repeat(lookupSymbolSize) {
|
||||
val name = readUTF()
|
||||
val scope = readUTF()
|
||||
lookupSymbols.add(LookupSymbol(name = name, scope = scope))
|
||||
}
|
||||
|
||||
val dirtyClassesSize = readInt()
|
||||
val dirtyClassesFqNames = ArrayList<FqName>(dirtyClassesSize)
|
||||
repeat(dirtyClassesSize) {
|
||||
val fqNameString = readUTF()
|
||||
dirtyClassesFqNames.add(FqName(fqNameString))
|
||||
}
|
||||
|
||||
return DirtyData(lookupSymbols, dirtyClassesFqNames)
|
||||
}
|
||||
|
||||
private fun ObjectOutputStream.writeDirtyData(dirtyData: DirtyData) {
|
||||
val lookupSymbols = dirtyData.dirtyLookupSymbols
|
||||
writeInt(lookupSymbols.size)
|
||||
for ((name, scope) in lookupSymbols) {
|
||||
writeUTF(name)
|
||||
writeUTF(scope)
|
||||
}
|
||||
|
||||
val dirtyClassesFqNames = dirtyData.dirtyClassesFqNames
|
||||
writeInt(dirtyClassesFqNames.size)
|
||||
for (fqName in dirtyClassesFqNames) {
|
||||
writeUTF(fqName.asString())
|
||||
}
|
||||
}
|
||||
|
||||
internal val MAX_DIFFS_ENTRIES: Int = 10
|
||||
|
||||
@set:TestOnly
|
||||
var CURRENT_VERSION: Int = 0
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.incremental
|
||||
|
||||
import java.io.*
|
||||
|
||||
internal data class BuildInfo(val startTS: Long) : Serializable {
|
||||
data class BuildInfo(val startTS: Long) : Serializable {
|
||||
companion object {
|
||||
fun read(file: File): BuildInfo? =
|
||||
try {
|
||||
|
||||
+15
-10
@@ -255,16 +255,9 @@ abstract class IncrementalCompilerRunner<
|
||||
if (exitCode == ExitCode.OK && compilationMode is CompilationMode.Incremental) {
|
||||
buildDirtyLookupSymbols.addAll(additionalDirtyLookupSymbols())
|
||||
}
|
||||
if (changesRegistry != null) {
|
||||
if (compilationMode is CompilationMode.Incremental) {
|
||||
val dirtyData = DirtyData(buildDirtyLookupSymbols, buildDirtyFqNames)
|
||||
changesRegistry.registerChanges(currentBuildInfo.startTS, dirtyData)
|
||||
}
|
||||
else {
|
||||
assert(compilationMode is CompilationMode.Rebuild) { "Unexpected compilation mode: ${compilationMode::class.java}" }
|
||||
changesRegistry.unknownChanges(currentBuildInfo.startTS)
|
||||
}
|
||||
}
|
||||
|
||||
val dirtyData = DirtyData(buildDirtyLookupSymbols, buildDirtyFqNames)
|
||||
processChangesAfterBuild(compilationMode, currentBuildInfo, dirtyData)
|
||||
|
||||
if (exitCode == ExitCode.OK) {
|
||||
cacheVersions.forEach { it.saveIfNeeded() }
|
||||
@@ -273,6 +266,18 @@ abstract class IncrementalCompilerRunner<
|
||||
return exitCode
|
||||
}
|
||||
|
||||
protected open fun processChangesAfterBuild(compilationMode: CompilationMode, currentBuildInfo: BuildInfo, dirtyData: DirtyData) {
|
||||
if (changesRegistry == null) return
|
||||
|
||||
if (compilationMode is CompilationMode.Incremental) {
|
||||
changesRegistry.registerChanges(currentBuildInfo.startTS, dirtyData)
|
||||
}
|
||||
else {
|
||||
assert(compilationMode is CompilationMode.Rebuild) { "Unexpected compilation mode: ${compilationMode::class.java}" }
|
||||
changesRegistry.unknownChanges(currentBuildInfo.startTS)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DIRTY_SOURCES_FILE_NAME = "dirty-sources.txt"
|
||||
const val LAST_BUILD_INFO_FILE_NAME = "last-build.bin"
|
||||
|
||||
+73
-23
@@ -16,10 +16,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.incremental
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.kotlin.annotation.AnnotationFileUpdater
|
||||
import org.jetbrains.kotlin.build.GeneratedFile
|
||||
import org.jetbrains.kotlin.build.GeneratedJvmClass
|
||||
import org.jetbrains.kotlin.build.isModuleMappingFile
|
||||
import org.jetbrains.kotlin.build.JvmSourceRoot
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import kotlin.collections.HashSet
|
||||
|
||||
fun makeIncrementally(
|
||||
cachesDir: File,
|
||||
@@ -89,7 +90,9 @@ class IncrementalJvmCompilerRunner(
|
||||
reporter: ICReporter,
|
||||
private var kaptAnnotationsFileUpdater: AnnotationFileUpdater? = null,
|
||||
artifactChangesProvider: ArtifactChangesProvider? = null,
|
||||
changesRegistry: ChangesRegistry? = null
|
||||
changesRegistry: ChangesRegistry? = null,
|
||||
private val buildHistoryFile: File? = null,
|
||||
private val friendBuildHistoryFile: File? = null
|
||||
) : IncrementalCompilerRunner<K2JVMCompilerArguments, IncrementalJvmCachesManager>(
|
||||
workingDir,
|
||||
"caches-jvm",
|
||||
@@ -110,16 +113,58 @@ class IncrementalJvmCompilerRunner(
|
||||
private var javaFilesProcessor = ChangedJavaFilesProcessor(reporter)
|
||||
|
||||
override fun calculateSourcesToCompile(caches: IncrementalJvmCachesManager, changedFiles: ChangedFiles.Known, args: K2JVMCompilerArguments): CompilationMode {
|
||||
val removedClassFiles = changedFiles.removed.filter(File::isClassFile)
|
||||
if (removedClassFiles.any()) return CompilationMode.Rebuild { "Removed class files: ${reporter.pathsAsString(removedClassFiles)}" }
|
||||
val dirtyFiles = getDirtyFiles(changedFiles)
|
||||
|
||||
val modifiedClassFiles = changedFiles.modified.filter(File::isClassFile)
|
||||
if (modifiedClassFiles.any()) return CompilationMode.Rebuild { "Modified class files: ${reporter.pathsAsString(modifiedClassFiles)}" }
|
||||
fun markDirtyBy(lookupSymbols: Collection<LookupSymbol>) {
|
||||
if (lookupSymbols.isEmpty()) return
|
||||
|
||||
val dirtyFilesFromLookups = mapLookupSymbolsToFiles(caches.lookupCache, lookupSymbols, reporter)
|
||||
dirtyFiles.addAll(dirtyFilesFromLookups)
|
||||
}
|
||||
|
||||
fun markDirtyBy(dirtyClassesFqNames: Collection<FqName>) {
|
||||
if (dirtyClassesFqNames.isEmpty()) return
|
||||
|
||||
val fqNamesWithSubtypes = dirtyClassesFqNames.flatMap { withSubtypes(it, listOf(caches.platformCache)) }
|
||||
val dirtyFilesFromFqNames = mapClassesFqNamesToFiles(listOf(caches.platformCache), fqNamesWithSubtypes, reporter)
|
||||
dirtyFiles.addAll(dirtyFilesFromFqNames)
|
||||
}
|
||||
|
||||
val lastBuildInfo = BuildInfo.read(lastBuildInfoFile)
|
||||
reporter.report { "Last Kotlin Build info -- $lastBuildInfo" }
|
||||
|
||||
val changesFromFriend by lazy {
|
||||
val myLastTS = lastBuildInfo?.startTS ?: return@lazy ChangesEither.Unknown()
|
||||
val storage = friendBuildHistoryFile?.let { BuildDiffsStorage.readFromFile(it, reporter) } ?: return@lazy ChangesEither.Unknown()
|
||||
|
||||
val (prevDiffs, newDiffs) = storage.buildDiffs.partition { it.ts < myLastTS }
|
||||
if (prevDiffs.isEmpty()) return@lazy ChangesEither.Unknown()
|
||||
|
||||
val dirtyLookupSymbols = HashSet<LookupSymbol>()
|
||||
val dirtyClassesFqNames = HashSet<FqName>()
|
||||
for ((_, isIncremental, dirtyData) in newDiffs) {
|
||||
if (!isIncremental) return@lazy ChangesEither.Unknown()
|
||||
|
||||
dirtyLookupSymbols.addAll(dirtyData.dirtyLookupSymbols)
|
||||
dirtyClassesFqNames.addAll(dirtyData.dirtyClassesFqNames)
|
||||
}
|
||||
|
||||
markDirtyBy(dirtyLookupSymbols)
|
||||
markDirtyBy(dirtyClassesFqNames)
|
||||
ChangesEither.Known(dirtyLookupSymbols, dirtyClassesFqNames)
|
||||
}
|
||||
val friendDirs = args.friendPaths?.map { File(it) } ?: emptyList()
|
||||
for (file in changedFiles.removed.asSequence() + changedFiles.modified.asSequence()) {
|
||||
if (!file.isClassFile()) continue
|
||||
|
||||
val isFriendClassFile = friendDirs.any { FileUtil.isAncestor(it, file, false) }
|
||||
if (isFriendClassFile && changesFromFriend is ChangesEither.Known) continue
|
||||
|
||||
return CompilationMode.Rebuild { "Cannot get changes from modified or removed class file: ${reporter.pathsAsString(file)}" }
|
||||
}
|
||||
|
||||
val classpathSet = args.classpathAsList.toHashSet()
|
||||
val modifiedClasspathEntries = changedFiles.modified.filter { it in classpathSet }
|
||||
val lastBuildInfo = BuildInfo.read(lastBuildInfoFile)
|
||||
reporter.report { "Last Kotlin Build info -- $lastBuildInfo" }
|
||||
val classpathChanges = getClasspathChanges(modifiedClasspathEntries, lastBuildInfo)
|
||||
if (classpathChanges !is ChangesEither.Known) {
|
||||
return CompilationMode.Rebuild { "could not get changes from modified classpath entries: ${reporter.pathsAsString(modifiedClasspathEntries)}" }
|
||||
@@ -131,21 +176,9 @@ class IncrementalJvmCompilerRunner(
|
||||
is ChangesEither.Unknown -> return CompilationMode.Rebuild { "Could not get changes for java files" }
|
||||
}
|
||||
|
||||
val dirtyFiles = getDirtyFiles(changedFiles)
|
||||
val lookupSymbols = HashSet<LookupSymbol>()
|
||||
lookupSymbols.addAll(affectedJavaSymbols)
|
||||
lookupSymbols.addAll(classpathChanges.lookupSymbols)
|
||||
|
||||
if (lookupSymbols.any()) {
|
||||
val dirtyFilesFromLookups = mapLookupSymbolsToFiles(caches.lookupCache, lookupSymbols, reporter)
|
||||
dirtyFiles.addAll(dirtyFilesFromLookups)
|
||||
}
|
||||
|
||||
val dirtyClassesFqNames = classpathChanges.fqNames.flatMap { withSubtypes(it, listOf(caches.platformCache)) }
|
||||
if (dirtyClassesFqNames.any()) {
|
||||
val dirtyFilesFromFqNames = mapClassesFqNamesToFiles(listOf(caches.platformCache), dirtyClassesFqNames, reporter)
|
||||
dirtyFiles.addAll(dirtyFilesFromFqNames)
|
||||
}
|
||||
markDirtyBy(affectedJavaSymbols)
|
||||
markDirtyBy(classpathChanges.lookupSymbols)
|
||||
markDirtyBy(classpathChanges.fqNames)
|
||||
|
||||
return CompilationMode.Incremental(dirtyFiles)
|
||||
}
|
||||
@@ -263,6 +296,23 @@ class IncrementalJvmCompilerRunner(
|
||||
override fun additionalDirtyLookupSymbols(): Iterable<LookupSymbol> =
|
||||
javaFilesProcessor.allChangedSymbols
|
||||
|
||||
override fun processChangesAfterBuild(compilationMode: CompilationMode, currentBuildInfo: BuildInfo, dirtyData: DirtyData) {
|
||||
super.processChangesAfterBuild(compilationMode, currentBuildInfo, dirtyData)
|
||||
|
||||
if (buildHistoryFile == null) return
|
||||
|
||||
val prevDiffs = BuildDiffsStorage.readFromFile(buildHistoryFile, reporter)?.buildDiffs ?: emptyList()
|
||||
val newDiff = if (compilationMode is CompilationMode.Incremental) {
|
||||
BuildDifference(currentBuildInfo.startTS, true, dirtyData)
|
||||
}
|
||||
else {
|
||||
val emptyDirtyData = DirtyData()
|
||||
BuildDifference(currentBuildInfo.startTS, false, emptyDirtyData)
|
||||
}
|
||||
|
||||
BuildDiffsStorage.writeToFile(buildHistoryFile, BuildDiffsStorage(prevDiffs + newDiff), reporter)
|
||||
}
|
||||
|
||||
override fun makeServices(
|
||||
args: K2JVMCompilerArguments,
|
||||
lookupTracker: LookupTracker,
|
||||
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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
|
||||
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.junit.After
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
import java.io.OutputStream
|
||||
import java.util.*
|
||||
|
||||
class BuildDiffsStorageTest {
|
||||
lateinit var storageFile: File
|
||||
private val random = Random(System.currentTimeMillis())
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
storageFile = File.createTempFile("BuildDiffsStorageTest", "storage")
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
storageFile.delete()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testToString() {
|
||||
val lookupSymbols = listOf(LookupSymbol("foo", "bar"))
|
||||
val fqNames = listOf(FqName("fizz.Buzz"))
|
||||
val diff = BuildDifference(100, true, DirtyData(lookupSymbols, fqNames))
|
||||
val diffs = BuildDiffsStorage(listOf(diff))
|
||||
Assert.assertEquals("BuildDiffsStorage(buildDiffs=[BuildDifference(ts=100, isIncremental=true, dirtyData=DirtyData(dirtyLookupSymbols=[LookupSymbol(name=foo, scope=bar)], dirtyClassesFqNames=[fizz.Buzz]))])",
|
||||
diffs.toString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun writeReadSimple() {
|
||||
val diffs = BuildDiffsStorage(listOf(getRandomDiff()))
|
||||
BuildDiffsStorage.writeToFile(storageFile, diffs, reporter = null)
|
||||
|
||||
val diffsDeserialized = BuildDiffsStorage.readFromFile(storageFile, reporter = null)
|
||||
Assert.assertEquals(diffs.toString(), diffsDeserialized.toString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun writeReadMany() {
|
||||
val generated = Array(20) { getRandomDiff() }.toList()
|
||||
val diffs = BuildDiffsStorage(generated)
|
||||
BuildDiffsStorage.writeToFile(storageFile, diffs, reporter = null)
|
||||
|
||||
val diffsDeserialized = BuildDiffsStorage.readFromFile(storageFile, reporter = null)
|
||||
val expected = generated.sortedBy { it.ts }.takeLast(BuildDiffsStorage.MAX_DIFFS_ENTRIES).toTypedArray()
|
||||
Assert.assertArrayEquals(expected, diffsDeserialized?.buildDiffs?.toTypedArray())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun readFileNotExist() {
|
||||
storageFile.delete()
|
||||
|
||||
val diffsDeserialized = BuildDiffsStorage.readFromFile(storageFile, reporter = null)
|
||||
Assert.assertEquals(null, diffsDeserialized)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun versionChanged() {
|
||||
val diffs = BuildDiffsStorage(listOf(getRandomDiff()))
|
||||
BuildDiffsStorage.writeToFile(storageFile, diffs, reporter = null)
|
||||
|
||||
val versionBackup = BuildDiffsStorage.CURRENT_VERSION
|
||||
try {
|
||||
BuildDiffsStorage.CURRENT_VERSION++
|
||||
val diffsDeserialized = BuildDiffsStorage.readFromFile(storageFile, reporter = null)
|
||||
Assert.assertEquals(null, diffsDeserialized)
|
||||
}
|
||||
finally {
|
||||
BuildDiffsStorage.CURRENT_VERSION = versionBackup
|
||||
}
|
||||
}
|
||||
|
||||
private fun getRandomDiff(): BuildDifference {
|
||||
val ts = random.nextLong()
|
||||
val lookupSymbols = listOf(LookupSymbol("foo", "bar"))
|
||||
val fqNames = listOf(FqName("fizz.Buzz"))
|
||||
return BuildDifference(ts, true, DirtyData(lookupSymbols, fqNames))
|
||||
}
|
||||
}
|
||||
+22
-4
@@ -20,10 +20,7 @@ import org.gradle.api.logging.LogLevel
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import org.jetbrains.kotlin.gradle.plugin.CopyClassesToJavaOutputStatus
|
||||
import org.jetbrains.kotlin.gradle.tasks.USING_INCREMENTAL_COMPILATION_MESSAGE
|
||||
import org.jetbrains.kotlin.gradle.util.checkBytecodeContains
|
||||
import org.jetbrains.kotlin.gradle.util.getFileByName
|
||||
import org.jetbrains.kotlin.gradle.util.getFilesByNames
|
||||
import org.jetbrains.kotlin.gradle.util.modify
|
||||
import org.jetbrains.kotlin.gradle.util.*
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
import java.util.zip.ZipFile
|
||||
@@ -490,6 +487,27 @@ class KotlinGradleIT: BaseGradleIT() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIncrementalTestCompile() {
|
||||
val project = Project("kotlinProject", GRADLE_VERSION)
|
||||
val options = defaultBuildOptions().copy(incremental = true)
|
||||
|
||||
project.build("build", options = options) {
|
||||
assertSuccessful()
|
||||
}
|
||||
|
||||
val joinerKt = project.projectDir.getFileByName("KotlinGreetingJoiner.kt")
|
||||
joinerKt.modify {
|
||||
it.replace("class KotlinGreetingJoiner", "internal class KotlinGreetingJoiner")
|
||||
}
|
||||
|
||||
project.build("build", options = options) {
|
||||
assertSuccessful()
|
||||
val testJoinerKt = project.projectDir.getFileByName("TestKotlinGreetingJoiner.kt")
|
||||
assertCompiledKotlinSources(project.relativize(joinerKt, testJoinerKt))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testLanguageVersionApiVersionExplicit() {
|
||||
val project = Project("kotlinProject", "3.3")
|
||||
|
||||
+6
-21
@@ -1,15 +1,13 @@
|
||||
package org.jetbrains.kotlin.gradle
|
||||
|
||||
import org.jetbrains.kotlin.gradle.util.allKotlinFiles
|
||||
import org.jetbrains.kotlin.gradle.util.getFileByName
|
||||
import org.jetbrains.kotlin.gradle.util.modify
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
|
||||
class TestRootAffectedIT : BaseGradleIT() {
|
||||
@Test
|
||||
fun testSourceRootClassIsModifiedIC() {
|
||||
val project = Project("kotlinProject", "2.10")
|
||||
val project = Project("kotlinProject", "4.1")
|
||||
val buildOptions = defaultBuildOptions().copy(incremental = true)
|
||||
|
||||
project.build("build", options = buildOptions) {
|
||||
@@ -26,8 +24,8 @@ class TestRootAffectedIT : BaseGradleIT() {
|
||||
|
||||
project.build("build", options = buildOptions) {
|
||||
assertSuccessful()
|
||||
val expectedToCompile = project.relativize(listOf(kotlinGreetingJoinerFile) + project.allTestKotlinFiles())
|
||||
assertCompiledKotlinSources(expectedToCompile)
|
||||
val testKotlinGreetingJoinerFile = project.projectDir.getFileByName("TestKotlinGreetingJoiner.kt")
|
||||
assertCompiledKotlinSources(project.relativize(kotlinGreetingJoinerFile, testKotlinGreetingJoinerFile))
|
||||
}
|
||||
|
||||
project.build("build", options = buildOptions) {
|
||||
@@ -38,7 +36,8 @@ class TestRootAffectedIT : BaseGradleIT() {
|
||||
|
||||
@Test
|
||||
fun testSourceRootClassIsRemovedIC() {
|
||||
val project = Project("kotlinProject", "2.10")
|
||||
// todo: update Gradle after https://github.com/gradle/gradle/issues/3051 is resolved
|
||||
val project = Project("kotlinProject", "3.0")
|
||||
val buildOptions = defaultBuildOptions().copy(incremental = true)
|
||||
|
||||
project.build("build", options = buildOptions) {
|
||||
@@ -48,12 +47,6 @@ class TestRootAffectedIT : BaseGradleIT() {
|
||||
val dummyFile = project.projectDir.getFileByName("Dummy.kt")
|
||||
dummyFile.delete()
|
||||
|
||||
project.build("build", options = buildOptions) {
|
||||
assertSuccessful()
|
||||
val expectedToCompile = project.relativize(project.allTestKotlinFiles())
|
||||
assertCompiledKotlinSources(expectedToCompile)
|
||||
}
|
||||
|
||||
project.build("build", options = buildOptions) {
|
||||
assertSuccessful()
|
||||
assertCompiledKotlinSources(emptyList())
|
||||
@@ -62,7 +55,7 @@ class TestRootAffectedIT : BaseGradleIT() {
|
||||
|
||||
@Test
|
||||
fun testTestRootClassIsRemovedIC() {
|
||||
val project = Project("kotlinProject", "2.10")
|
||||
val project = Project("kotlinProject", "4.1")
|
||||
val buildOptions = defaultBuildOptions().copy(incremental = true)
|
||||
|
||||
project.build("build", options = buildOptions) {
|
||||
@@ -76,13 +69,5 @@ class TestRootAffectedIT : BaseGradleIT() {
|
||||
assertSuccessful()
|
||||
assertCompiledKotlinSources(emptyList())
|
||||
}
|
||||
|
||||
project.build("build", options = buildOptions) {
|
||||
assertSuccessful()
|
||||
assertCompiledKotlinSources(emptyList())
|
||||
}
|
||||
}
|
||||
|
||||
private fun Project.allTestKotlinFiles(): Iterable<File> =
|
||||
File(projectDir, "src/test").allKotlinFiles()
|
||||
}
|
||||
+3
-1
@@ -36,5 +36,7 @@ internal class GradleIncrementalCompilerEnvironment(
|
||||
compilerArgs: CommonCompilerArguments,
|
||||
val kaptAnnotationsFileUpdater: AnnotationFileUpdater? = null,
|
||||
val artifactDifferenceRegistryProvider: ArtifactDifferenceRegistryProvider? = null,
|
||||
val artifactFile: File? = null
|
||||
val artifactFile: File? = null,
|
||||
val buildHistoryFile: File? = null,
|
||||
val friendBuildHistoryFile: File? = null
|
||||
) : GradleCompilerEnvironment(compilerClasspath, messageCollector, outputItemsCollector, compilerArgs)
|
||||
+3
-1
@@ -255,7 +255,9 @@ internal class GradleCompilerRunner(private val project: Project) : KotlinCompil
|
||||
reportSeverity = reportSeverity(verbose),
|
||||
requestedCompilationResults = arrayOf(CompilationResultCategory.IC_COMPILE_ITERATION.code),
|
||||
compilerMode = CompilerMode.INCREMENTAL_COMPILER,
|
||||
targetPlatform = targetPlatform
|
||||
targetPlatform = targetPlatform,
|
||||
resultDifferenceFile = environment.buildHistoryFile,
|
||||
friendDifferenceFile = environment.friendBuildHistoryFile
|
||||
)
|
||||
val servicesFacade = GradleIncrementalCompilerServicesFacadeImpl(project, environment)
|
||||
val argsArray = ArgumentUtils.convertArgumentsToStringList(environment.compilerArgs).toTypedArray()
|
||||
|
||||
+5
-1
@@ -243,6 +243,7 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
|
||||
internal open val sourceRootsContainer = FilteringSourceRootsContainer()
|
||||
|
||||
private var kaptAnnotationsFileUpdater: AnnotationFileUpdater? = null
|
||||
val buildHistoryFile: File = File(taskBuildDirectory, "build-history.bin")
|
||||
|
||||
val kaptOptions = KaptOptions()
|
||||
|
||||
@@ -316,10 +317,13 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
|
||||
!incremental -> GradleCompilerEnvironment(computedCompilerClasspath, messageCollector, outputItemCollector, args)
|
||||
else -> {
|
||||
logger.warn(USING_INCREMENTAL_COMPILATION_MESSAGE)
|
||||
val friendTask = friendTaskName?.let { project.tasks.findByName(it) as? KotlinCompile }
|
||||
GradleIncrementalCompilerEnvironment(computedCompilerClasspath, changedFiles, reporter, taskBuildDirectory,
|
||||
messageCollector, outputItemCollector, args, kaptAnnotationsFileUpdater,
|
||||
artifactDifferenceRegistryProvider,
|
||||
artifactFile)
|
||||
artifactFile = artifactFile,
|
||||
buildHistoryFile = buildHistoryFile,
|
||||
friendBuildHistoryFile = friendTask?.buildHistoryFile)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user