JPS: Refactor cache compatibility checking and build targets loading/dependency analysis.

CacheVersion class refactoring:

Responsibilities of class CacheVersion are splitted into:
	- interface CacheAttributesManager<Attrs>, that should:
	    - load actual cache attribute values from FS
	    - provide expected attribute values (that is required for current build)
	    - checks when the existed cache (with actual attributes) values is suitable for current build (expected atribute values)
	    - write new values to FS for next build
	- CacheAttributesDiff is created by calling CacheAttributesManager.loadDiff extension method. This is just pair of actual and expected cache attributes values, with reference to manager. Result of loadDiff can be saved.

CacheAttributesDiff are designed to be used as facade of attributes operations: CacheAttributesDiff.status are calculated based on actual and expected attribute values. Based on that status system may perform required actions (i.e. rebuild something, clearing caches, etc...).

Methods of CacheAttributesManager other then loadDiff should be used only through CacheAttributesDiff.
Build system should work in this order:
    - get implementation of CacheAttributesManager for particular compiler and cache
    - call loadDiff __once__ and save it result
    - perform actions based on `diff.status`
    - save new cache attribute values by calling `diff.saveExpectedIfNeeded()`

There are 2 implementation of CacheAttributesManager:
    - CacheVersionManager that simple checks cache version number.
    - CompositeLookupsCacheAttributesManager - manager for global lookups cache that may contain lookups for several compilers (jvm, js).

Gradle:

Usages of CacheVersion in gradle are kept as is. For compatibility this methods are added: CacheAttributesManager.saveIfNeeded, CacheAttributesManager.clean. This methods should not be used in new code.

JPS:

All JPS logic that was responsible for cache version checking completely rewritten.

To write proper implementation for version checking, this things also changed:
	- KotlinCompileContext introduced. This context lives between first calling build of kotlin target until build finish. As of now all kotlin targets are loaded on KotlinCompileContext initialization. This is required to collect kotlin target types used in this build (jvm/js). Also all build-wide logic are moved from KotlinBuilder to KotlinCompileContext. Chunk dependency calculation also moved to build start which improves performance for big projects #KT-26113
	- Kotlin bindings to JPS build targets also stored in KotlinCompileContext, and binding is fixed. Previously it is stored in local Context and reacreated for each chunk, now they stored in KotlinCompileContext which is binded by GlobalContextKey with this exception: source roots are calculated for each round, since temporary source roots with groovy stubs are created at build time and visible only in local compile context.
	- KotlinChunk introduced. All chunk-wide logic are moved from KotlinModuleBuildTarget (i.e compiler, language, cache version checking and dependent cache loading)
	- Fix legacy MPP common dependent modules

Cache version checking logic now works as following:
- At first chunk building all targets are loaded and used platforms are collected. Lookups cache manger is created based on this set. Actual cache attributes are loaded from FS. Based on CacheAttributesDiff.status this actions are performed: if cache is invalid all kotlin will be rebuilt. If cache is not required anymore it will be cleaned.
- Before build of each chunk local chunk cache attributes will be checked. If cache is invalid, chunk will be rebuilt. If cache is not required anymore it will be cleaned.

#KT-26113 Fixed
#KT-26072 Fixed

Original commit: 437fc9d749
This commit is contained in:
Sergey Rostov
2018-08-16 13:35:32 +03:00
parent dc022aef69
commit aa1eb9795d
55 changed files with 1509 additions and 781 deletions
@@ -16,14 +16,13 @@
package org.jetbrains.kotlin.jps.build
import org.jetbrains.jps.incremental.ModuleBuildTarget
import org.jetbrains.kotlin.incremental.testingUtils.BuildLogFinder
import org.jetbrains.kotlin.jps.incremental.CacheVersionProvider
import org.jetbrains.kotlin.jps.targets.KotlinModuleBuildTarget
abstract class AbstractDataContainerVersionChangedTest : AbstractIncrementalCacheVersionChangedTest() {
override val buildLogFinder: BuildLogFinder
get() = BuildLogFinder(isDataContainerBuildLogEnabled = true)
override fun getVersions(cacheVersionProvider: CacheVersionProvider, targets: Iterable<ModuleBuildTarget>) =
listOf(cacheVersionProvider.dataContainerVersion())
override fun getVersionManagersToTest(target: KotlinModuleBuildTarget<*>) =
listOf(kotlinCompileContext.lookupsCacheAttributesManager.versionManagerForTesting)
}
@@ -16,15 +16,14 @@
package org.jetbrains.kotlin.jps.build
import org.jetbrains.jps.incremental.ModuleBuildTarget
import org.jetbrains.kotlin.incremental.storage.version.CacheVersionManager
import org.jetbrains.kotlin.incremental.testingUtils.Modification
import org.jetbrains.kotlin.incremental.testingUtils.ModifyContent
import org.jetbrains.kotlin.jps.incremental.CacheVersionProvider
import org.jetbrains.kotlin.jps.targets.KotlinModuleBuildTarget
abstract class AbstractIncrementalCacheVersionChangedTest : AbstractIncrementalJpsTest(allowNoFilesWithSuffixInTestData = true) {
override fun performAdditionalModifications(modifications: List<Modification>) {
val modifiedFiles = modifications.filterIsInstance<ModifyContent>().map { it.path }
val paths = projectDescriptor.dataManager.dataPaths
val targets = projectDescriptor.allModuleTargets
val hasKotlin = HasKotlinMarker(projectDescriptor.dataManager)
@@ -33,13 +32,18 @@ abstract class AbstractIncrementalCacheVersionChangedTest : AbstractIncrementalJ
}
if (modifiedFiles.none { it.endsWith("do-not-change-cache-versions") }) {
val cacheVersionProvider = CacheVersionProvider(paths, isIncrementalCompilationEnabled = true)
val versions = getVersions(cacheVersionProvider, targets)
val versionFiles = versions.map { it.formatVersionFile }.filter { it.exists() }
versionFiles.forEach { it.writeText("777") }
val versions = targets.flatMap {
getVersionManagersToTest(kotlinCompileContext.targetsBinding[it]!!)
}
versions.forEach {
if (it.versionFileForTesting.exists()) {
it.versionFileForTesting.writeText("777")
}
}
}
}
protected open fun getVersions(cacheVersionProvider: CacheVersionProvider, targets: Iterable<ModuleBuildTarget>) =
targets.map { cacheVersionProvider.normalVersion(it) }
protected open fun getVersionManagersToTest(target: KotlinModuleBuildTarget<*>): List<CacheVersionManager> =
listOf(target.localCacheVersionManager)
}
@@ -44,13 +44,15 @@ import org.jetbrains.jps.model.java.JpsJavaDependencyScope
import org.jetbrains.jps.model.java.JpsJavaExtensionService
import org.jetbrains.jps.util.JpsPathUtil
import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.incremental.CacheVersion
import org.jetbrains.kotlin.incremental.LookupSymbol
import org.jetbrains.kotlin.incremental.isJavaFile
import org.jetbrains.kotlin.incremental.storage.version.CacheAttributesDiff
import org.jetbrains.kotlin.incremental.storage.version.CacheVersionManager
import org.jetbrains.kotlin.incremental.testingUtils.*
import org.jetbrains.kotlin.jps.incremental.CompositeLookupsCacheAttributesManager
import org.jetbrains.kotlin.jps.incremental.getKotlinCache
import org.jetbrains.kotlin.jps.incremental.withLookupStorage
import org.jetbrains.kotlin.jps.platforms.kotlinBuildTargets
import org.jetbrains.kotlin.jps.targets.KotlinModuleBuildTarget
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.keysToMap
@@ -82,6 +84,8 @@ abstract class AbstractIncrementalJpsTest(
protected var mapWorkingToOriginalFile: MutableMap<File, File> = hashMapOf()
lateinit var kotlinCompileContext: KotlinCompileContext
protected open val buildLogFinder: BuildLogFinder
get() = BuildLogFinder()
@@ -145,19 +149,21 @@ abstract class AbstractIncrementalJpsTest(
projectDescriptor = createProjectDescriptor(BuildLoggingManager(logger))
val lookupTracker = TestLookupTracker()
projectDescriptor.project.setTestingContext(TestingContext(lookupTracker, logger))
val testingContext = TestingContext(lookupTracker, logger)
projectDescriptor.project.setTestingContext(testingContext)
try {
val builder = IncProjectBuilder(projectDescriptor, BuilderRegistry.getInstance(), myBuildParams, CanceledStatus.NULL, mockConstantSearch, true)
val buildResult = BuildResult()
builder.addMessageHandler(buildResult)
val finalScope = scope.build()
builder.build(finalScope, false)
lookupTracker.lookups.mapTo(lookupsDuringTest) { LookupSymbol(it.name, it.scopeFqName) }
// testingContext.kotlinCompileContext is initialized in KotlinBuilder.initializeKotlinContext
kotlinCompileContext = testingContext.kotlinCompileContext!!
// for getting kotlin platform only
val dummyCompileContext = CompileContextImpl.createContextForTests(finalScope, projectDescriptor)
lookupTracker.lookups.mapTo(lookupsDuringTest) { LookupSymbol(it.name, it.scopeFqName) }
if (!buildResult.isSuccessful) {
val errorMessages =
@@ -169,7 +175,7 @@ abstract class AbstractIncrementalJpsTest(
return MakeResult(logger.log + "$COMPILATION_FAILED\n" + errorMessages + "\n", true, null)
}
else {
return MakeResult(logger.log, false, createMappingsDump(projectDescriptor, dummyCompileContext))
return MakeResult(logger.log, false, createMappingsDump(projectDescriptor))
}
}
finally {
@@ -287,20 +293,18 @@ abstract class AbstractIncrementalJpsTest(
}
private fun createMappingsDump(
project: ProjectDescriptor,
dummyCompileContext: CompileContext
) = createKotlinIncrementalCacheDump(project, dummyCompileContext) + "\n\n\n" +
project: ProjectDescriptor
) = createKotlinIncrementalCacheDump(project) + "\n\n\n" +
createLookupCacheDump(project) + "\n\n\n" +
createCommonMappingsDump(project) + "\n\n\n" +
createJavaMappingsDump(project)
private fun createKotlinIncrementalCacheDump(
project: ProjectDescriptor,
dummyCompileContext: CompileContext
project: ProjectDescriptor
): String {
return buildString {
for (target in project.allModuleTargets.sortedBy { it.presentableName }) {
val kotlinCache = project.dataManager.getKotlinCache(dummyCompileContext.kotlinBuildTargets[target])
val kotlinCache = project.dataManager.getKotlinCache(kotlinCompileContext.targetsBinding[target])
if (kotlinCache != null) {
append("<target $target>\n")
append(kotlinCache.dump())
@@ -443,14 +447,23 @@ abstract class AbstractIncrementalJpsTest(
override fun doGetProjectDir(): File? = workDir
private class MyLogger(val rootPath: String) : ProjectBuilderLoggerBase(), BuildLogger {
private class MyLogger(val rootPath: String) : ProjectBuilderLoggerBase(), TestingBuildLogger {
private val markedDirtyBeforeRound = ArrayList<File>()
private val markedDirtyAfterRound = ArrayList<File>()
override fun actionsOnCacheVersionChanged(actions: List<CacheVersion.Action>) {
if (actions.size > 1 && actions.any { it != CacheVersion.Action.DO_NOTHING }) {
logLine("Actions after cache changed: $actions")
override fun invalidOrUnusedCache(
chunk: KotlinChunk?,
target: KotlinModuleBuildTarget<*>?,
attributesDiff: CacheAttributesDiff<*>
) {
val cacheManager = attributesDiff.manager
val cacheTitle = when (cacheManager) {
is CacheVersionManager -> "Local cache for ${chunk ?: target}"
is CompositeLookupsCacheAttributesManager -> "Lookups cache"
else -> error("Unknown cache manager $cacheManager")
}
logLine("$cacheTitle are $attributesDiff")
}
override fun markedAsDirtyBeforeRound(files: Iterable<File>) {
@@ -461,13 +474,15 @@ abstract class AbstractIncrementalJpsTest(
markedDirtyAfterRound.addAll(files)
}
override fun buildStarted(context: CompileContext, chunk: ModuleChunk) {
override fun chunkBuildStarted(context: CompileContext, chunk: ModuleChunk) {
logDirtyFiles(markedDirtyBeforeRound) // files can be marked as dirty during build start (KotlinCompileContext initialization)
if (!chunk.isDummy(context) && context.projectDescriptor.project.modules.size > 1) {
logLine("Building ${chunk.modules.sortedBy { it.name }.joinToString { it.name }}")
}
}
override fun afterBuildStarted(context: CompileContext, chunk: ModuleChunk) {
override fun afterChunkBuildStarted(context: CompileContext, chunk: ModuleChunk) {
logDirtyFiles(markedDirtyBeforeRound)
}
@@ -44,13 +44,14 @@ import org.jetbrains.jps.model.java.JpsJavaDependencyScope
import org.jetbrains.jps.model.java.JpsJavaExtensionService
import org.jetbrains.jps.util.JpsPathUtil
import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.incremental.CacheVersion
import org.jetbrains.kotlin.incremental.LookupSymbol
import org.jetbrains.kotlin.incremental.isJavaFile
import org.jetbrains.kotlin.incremental.storage.version.CacheAttributesDiff
import org.jetbrains.kotlin.incremental.storage.version.CacheVersionManager
import org.jetbrains.kotlin.incremental.testingUtils.*
import org.jetbrains.kotlin.jps.incremental.CompositeLookupsCacheAttributesManager
import org.jetbrains.kotlin.jps.incremental.getKotlinCache
import org.jetbrains.kotlin.jps.incremental.withLookupStorage
import org.jetbrains.kotlin.jps.platforms.kotlinBuildTargets
import org.jetbrains.kotlin.jps.targets.KotlinModuleBuildTarget
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.keysToMap
@@ -82,6 +83,8 @@ abstract class AbstractIncrementalJpsTest(
protected var mapWorkingToOriginalFile: MutableMap<File, File> = hashMapOf()
lateinit var kotlinCompileContext: KotlinCompileContext
protected open val buildLogFinder: BuildLogFinder
get() = BuildLogFinder()
@@ -144,19 +147,20 @@ abstract class AbstractIncrementalJpsTest(
projectDescriptor = createProjectDescriptor(BuildLoggingManager(logger))
val lookupTracker = TestLookupTracker()
projectDescriptor.project.setTestingContext(TestingContext(lookupTracker, logger))
val testingContext = TestingContext(lookupTracker, logger)
projectDescriptor.project.setTestingContext(testingContext)
try {
val builder = IncProjectBuilder(projectDescriptor, BuilderRegistry.getInstance(), myBuildParams, CanceledStatus.NULL, mockConstantSearch, true)
val buildResult = BuildResult()
builder.addMessageHandler(buildResult)
val finalScope = scope.build()
builder.build(finalScope, false)
lookupTracker.lookups.mapTo(lookupsDuringTest) { LookupSymbol(it.name, it.scopeFqName) }
// testingContext.kotlinCompileContext is initialized in KotlinBuilder.initializeKotlinContext
kotlinCompileContext = testingContext.kotlinCompileContext!!
// for getting kotlin platform only
val dummyCompileContext = CompileContextImpl.createContextForTests(finalScope, projectDescriptor)
if (!buildResult.isSuccessful) {
val errorMessages =
@@ -168,7 +172,7 @@ abstract class AbstractIncrementalJpsTest(
return MakeResult(logger.log + "$COMPILATION_FAILED\n" + errorMessages + "\n", true, null)
}
else {
return MakeResult(logger.log, false, createMappingsDump(projectDescriptor, dummyCompileContext))
return MakeResult(logger.log, false, createMappingsDump(projectDescriptor))
}
}
finally {
@@ -286,20 +290,18 @@ abstract class AbstractIncrementalJpsTest(
}
private fun createMappingsDump(
project: ProjectDescriptor,
dummyCompileContext: CompileContext
) = createKotlinIncrementalCacheDump(project, dummyCompileContext) + "\n\n\n" +
project: ProjectDescriptor
) = createKotlinIncrementalCacheDump(project) + "\n\n\n" +
createLookupCacheDump(project) + "\n\n\n" +
createCommonMappingsDump(project) + "\n\n\n" +
createJavaMappingsDump(project)
private fun createKotlinIncrementalCacheDump(
project: ProjectDescriptor,
dummyCompileContext: CompileContext
project: ProjectDescriptor
): String {
return buildString {
for (target in project.allModuleTargets.sortedBy { it.presentableName }) {
val kotlinCache = project.dataManager.getKotlinCache(dummyCompileContext.kotlinBuildTargets[target])
val kotlinCache = project.dataManager.getKotlinCache(kotlinCompileContext.targetsBinding[target])
if (kotlinCache != null) {
append("<target $target>\n")
append(kotlinCache.dump())
@@ -442,14 +444,23 @@ abstract class AbstractIncrementalJpsTest(
override fun doGetProjectDir(): File? = workDir
private class MyLogger(val rootPath: String) : ProjectBuilderLoggerBase(), BuildLogger {
private class MyLogger(val rootPath: String) : ProjectBuilderLoggerBase(), TestingBuildLogger {
private val markedDirtyBeforeRound = ArrayList<File>()
private val markedDirtyAfterRound = ArrayList<File>()
override fun actionsOnCacheVersionChanged(actions: List<CacheVersion.Action>) {
if (actions.size > 1 && actions.any { it != CacheVersion.Action.DO_NOTHING }) {
logLine("Actions after cache changed: $actions")
override fun invalidOrUnusedCache(
chunk: KotlinChunk?,
target: KotlinModuleBuildTarget<*>?,
attributesDiff: CacheAttributesDiff<*>
) {
val cacheManager = attributesDiff.manager
val cacheTitle = when (cacheManager) {
is CacheVersionManager -> "Local cache for ${chunk ?: target}"
is CompositeLookupsCacheAttributesManager -> "Lookups cache"
else -> error("Unknown cache manager $cacheManager")
}
logLine("$cacheTitle are $attributesDiff")
}
override fun markedAsDirtyBeforeRound(files: Iterable<File>) {
@@ -460,13 +471,15 @@ abstract class AbstractIncrementalJpsTest(
markedDirtyAfterRound.addAll(files)
}
override fun buildStarted(context: CompileContext, chunk: ModuleChunk) {
override fun chunkBuildStarted(context: CompileContext, chunk: ModuleChunk) {
logDirtyFiles(markedDirtyBeforeRound) // files can be marked as dirty during build start (KotlinCompileContext initialization)
if (!chunk.isDummy(context) && context.projectDescriptor.project.modules.size > 1) {
logLine("Building ${chunk.modules.sortedBy { it.name }.joinToString { it.name }}")
}
}
override fun afterBuildStarted(context: CompileContext, chunk: ModuleChunk) {
override fun afterChunkBuildStarted(context: CompileContext, chunk: ModuleChunk) {
logDirtyFiles(markedDirtyBeforeRound)
}
@@ -18,17 +18,14 @@ package org.jetbrains.kotlin.jps.build
import com.intellij.testFramework.UsefulTestCase
import org.jetbrains.jps.builders.BuildTarget
import org.jetbrains.jps.builders.CompileScopeTestBuilder
import org.jetbrains.jps.builders.storage.BuildDataPaths
import org.jetbrains.jps.incremental.CompileContextImpl
import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.incremental.KOTLIN_CACHE_DIRECTORY_NAME
import org.jetbrains.kotlin.incremental.storage.BasicMapsOwner
import org.jetbrains.kotlin.incremental.testingUtils.Modification
import org.jetbrains.kotlin.incremental.testingUtils.ModifyContent
import org.jetbrains.kotlin.jps.incremental.CacheVersionProvider
import org.jetbrains.kotlin.jps.incremental.KotlinDataContainerTarget
import org.jetbrains.kotlin.jps.platforms.kotlinBuildTargets
import org.jetbrains.kotlin.jps.targets.KotlinModuleBuildTarget
import org.jetbrains.kotlin.utils.Printer
import java.io.File
@@ -85,44 +82,55 @@ abstract class AbstractIncrementalLazyCachesTest : AbstractIncrementalJpsTest()
private fun dumpKotlinCachesFileNames(): String {
val sb = StringBuilder()
val p = Printer(sb)
val targets = projectDescriptor.allModuleTargets
val printer = Printer(sb)
val chunks = kotlinCompileContext.targetsIndex.chunks
val dataManager = projectDescriptor.dataManager
val paths = dataManager.dataPaths
val versions = CacheVersionProvider(paths, isIncrementalCompilationEnabled = true)
dumpCachesForTarget(p, paths, KotlinDataContainerTarget, versions.dataContainerVersion().formatVersionFile)
dumpCachesForTarget(
printer,
paths,
KotlinDataContainerTarget,
kotlinCompileContext.lookupsCacheAttributesManager.versionManagerForTesting.versionFileForTesting
)
// for getting kotlin platform only
val dummyCompileContext = CompileContextImpl.createContextForTests(CompileScopeTestBuilder.make().build(), projectDescriptor)
data class TargetInChunk(val chunk: KotlinChunk, val target: KotlinModuleBuildTarget<*>)
for (target in targets.sortedBy { it.presentableName }) {
val kotlinModuleBuildTarget = dummyCompileContext.kotlinBuildTargets[target]!!
val metaBuildInfo = kotlinModuleBuildTarget.buildMetaInfoFile(target, dataManager)
dumpCachesForTarget(p, paths, target,
versions.normalVersion(target).formatVersionFile,
metaBuildInfo,
subdirectory = KOTLIN_CACHE_DIRECTORY_NAME)
val allTargets = chunks.flatMap { chunk ->
chunk.targets.map { target ->
TargetInChunk(chunk, target)
}
}.sortedBy { it.target.jpsModuleBuildTarget.presentableName }
allTargets.forEach { (chunk, target) ->
val metaBuildInfo = chunk.buildMetaInfoFile(target.jpsModuleBuildTarget)
dumpCachesForTarget(
printer, paths, target.jpsModuleBuildTarget,
target.localCacheVersionManager.versionFileForTesting,
metaBuildInfo,
subdirectory = KOTLIN_CACHE_DIRECTORY_NAME
)
}
return sb.toString()
}
private fun dumpCachesForTarget(
p: Printer,
paths: BuildDataPaths,
target: BuildTarget<*>,
vararg cacheVersionsFiles: File,
subdirectory: String? = null
p: Printer,
paths: BuildDataPaths,
target: BuildTarget<*>,
vararg cacheVersionsFiles: File,
subdirectory: String? = null
) {
p.println(target)
p.pushIndent()
val dataRoot = paths.getTargetDataRoot(target).let { if (subdirectory != null) File(it, subdirectory) else it }
cacheVersionsFiles
.filter(File::exists)
.sortedBy { it.name }
.forEach { p.println(it.name) }
.filter(File::exists)
.sortedBy { it.name }
.forEach { p.println(it.name) }
kotlinCacheNames(dataRoot).sorted().forEach { p.println(it) }
@@ -58,13 +58,13 @@ import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.config.KotlinCompilerVersion.TEST_IS_PRE_RELEASE_SYSTEM_PROPERTY
import org.jetbrains.kotlin.incremental.CacheVersion
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.storage.version.CacheAttributesDiff
import org.jetbrains.kotlin.incremental.withIC
import org.jetbrains.kotlin.jps.build.KotlinJpsBuildTest.LibraryDependency.*
import org.jetbrains.kotlin.jps.model.kotlinCommonCompilerArguments
import org.jetbrains.kotlin.jps.model.kotlinCompilerArguments
import org.jetbrains.kotlin.jps.platforms.productionBuildTarget
import org.jetbrains.kotlin.jps.targets.KotlinModuleBuildTarget
import org.jetbrains.kotlin.load.kotlin.PackagePartClassUtils
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.test.KotlinTestUtils
@@ -970,6 +970,9 @@ open class KotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() {
}
}
// c -> b -exported-> a
// c2 -> b2 ------------^
val a = addModuleWithSourceAndTestRoot("a")
val b = addModuleWithSourceAndTestRoot("b")
val c = addModuleWithSourceAndTestRoot("c")
@@ -983,15 +986,21 @@ open class KotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() {
val actual = StringBuilder()
buildCustom(CanceledStatus.NULL, TestProjectBuilderLogger(), BuildResult()) {
project.setTestingContext(TestingContext(LookupTracker.DO_NOTHING, object : BuildLogger {
override fun buildStarted(context: CompileContext, chunk: ModuleChunk) {
actual.append("Targets dependent on ${chunk.targets.joinToString() }:\n")
actual.append(getDependentTargets(chunk.targets, context).map { it.toString() }.sorted().joinToString("\n"))
project.setTestingContext(TestingContext(LookupTracker.DO_NOTHING, object : TestingBuildLogger {
override fun chunkBuildStarted(context: CompileContext, chunk: ModuleChunk) {
actual.append("Targets dependent on ${chunk.targets.joinToString()}:\n")
val dependentRecursively = mutableSetOf<KotlinChunk>()
context.kotlin.getChunk(chunk)!!.collectDependentChunksRecursivelyExportedOnly(dependentRecursively)
dependentRecursively.asSequence().map { it.targets.joinToString() }.sorted().joinTo(actual, "\n")
actual.append("\n---------\n")
}
override fun afterBuildStarted(context: CompileContext, chunk: ModuleChunk) {}
override fun actionsOnCacheVersionChanged(actions: List<CacheVersion.Action>) {}
override fun afterChunkBuildStarted(context: CompileContext, chunk: ModuleChunk) {}
override fun invalidOrUnusedCache(
chunk: KotlinChunk?,
target: KotlinModuleBuildTarget<*>?,
attributesDiff: CacheAttributesDiff<*>
) {}
override fun buildFinished(exitCode: ModuleLevelBuilder.ExitCode) {}
override fun markedAsDirtyBeforeRound(files: Iterable<File>) {}
override fun markedAsDirtyAfterRound(files: Iterable<File>) {}
@@ -0,0 +1,82 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.jps.incremental
import org.jetbrains.kotlin.incremental.storage.version.CacheStatus
import org.jetbrains.kotlin.incremental.storage.version.loadDiff
import org.junit.Test
import java.io.File
import kotlin.test.assertEquals
class CompositeLookupsCacheAttributesManagerTest {
val manager = CompositeLookupsCacheAttributesManager(File("not-used"), setOf())
@Test
fun testNothingToJava() {
assertEquals(
CacheStatus.INVALID,
manager.loadDiff(
actual = null,
expected = CompositeLookupsCacheAttributes(1, setOf("jvm"))
).status
)
}
@Test
fun testNothingToJavaAndJs() {
assertEquals(
CacheStatus.INVALID,
manager.loadDiff(
actual = null,
expected = CompositeLookupsCacheAttributes(1, setOf("jvm", "js"))
).status
)
}
@Test
fun testJsToJava() {
assertEquals(
CacheStatus.INVALID,
manager.loadDiff(
actual = CompositeLookupsCacheAttributes(1, setOf("jvm")),
expected = CompositeLookupsCacheAttributes(1, setOf("js"))
).status
)
}
@Test
fun testJsAndJavaToJava() {
assertEquals(
CacheStatus.VALID,
manager.loadDiff(
actual = CompositeLookupsCacheAttributes(1, setOf("jvm", "js")),
expected = CompositeLookupsCacheAttributes(1, setOf("jvm"))
).status
)
}
@Test
fun testJsAndJavaToJavaWithOtherVersion() {
assertEquals(
CacheStatus.INVALID,
manager.loadDiff(
actual = CompositeLookupsCacheAttributes(1, setOf("jvm", "js")),
expected = CompositeLookupsCacheAttributes(2, setOf("jvm"))
).status
)
}
@Test
fun testJavaToJsAndJava() {
assertEquals(
CacheStatus.INVALID,
manager.loadDiff(
actual = CompositeLookupsCacheAttributes(1, setOf("jvm")),
expected = CompositeLookupsCacheAttributes(1, setOf("jvm", "js"))
).status
)
}
}