diff --git a/jps/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt b/jps/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt index 2ca8ef7c585..84706d4e7da 100644 --- a/jps/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt +++ b/jps/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt @@ -22,7 +22,10 @@ import com.intellij.openapi.util.io.FileUtil import com.intellij.util.containers.MultiMap import gnu.trove.THashSet import org.jetbrains.jps.ModuleChunk +import org.jetbrains.jps.builders.BuildTarget import org.jetbrains.jps.builders.DirtyFilesHolder +import org.jetbrains.jps.builders.impl.BuildTargetRegistryImpl +import org.jetbrains.jps.builders.impl.TargetOutputIndexImpl import org.jetbrains.jps.builders.java.JavaBuilderUtil import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor import org.jetbrains.jps.builders.java.dependencyView.Mappings @@ -102,9 +105,7 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR outputConsumer: ModuleLevelBuilder.OutputConsumer ): ModuleLevelBuilder.ExitCode { val messageCollector = MessageCollectorAdapter(context) - val dataManager = context.projectDescriptor.dataManager - val targets = chunk.targets - val incrementalCaches = targets.keysToMap { dataManager.getKotlinCache(it) } + val incrementalCaches = getIncrementalCaches(chunk, context) try { return doBuild(chunk, context, dirtyFilesHolder, messageCollector, outputConsumer, incrementalCaches) @@ -609,6 +610,44 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR } } +private val Iterable>.moduleTargets: Iterable + get() = filterIsInstance(javaClass()) + +private fun getIncrementalCaches(chunk: ModuleChunk, context: CompileContext): Map { + val dataManager = context.projectDescriptor.dataManager + val targets = chunk.targets + + val buildRegistry = BuildTargetRegistryImpl(context.projectDescriptor.model) + val outputIndex = TargetOutputIndexImpl(targets, context) + + val allTargets = buildRegistry.allTargets.moduleTargets + val allDependencies = allTargets.keysToMap { target -> + target.computeDependencies(buildRegistry, outputIndex).moduleTargets + } + + val dependents = targets.keysToMap { hashSetOf() } + val targetsWithDependents = HashSet(targets) + + for ((target, dependencies) in allDependencies) { + for (dependency in dependencies) { + if (dependency !in targets) continue + + dependents[dependency]!!.add(target) + targetsWithDependents.add(target) + } + } + + val caches = targetsWithDependents.keysToMap { dataManager.getKotlinCache(it) } + + for ((target, cache) in caches) { + dependents[target]?.forEach { + cache.addDependentCache(caches[it]!!) + } + } + + return caches +} + private val ALL_COMPILED_FILES_KEY = Key.create>("_all_kotlin_compiled_files_") private fun getAllCompiledFilesContainer(context: CompileContext): MutableSet { var allCompiledFiles = ALL_COMPILED_FILES_KEY.get(context) diff --git a/jps/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt b/jps/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt index baca0cc86b0..bea3d270cca 100644 --- a/jps/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt +++ b/jps/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt @@ -27,6 +27,7 @@ import org.jetbrains.annotations.TestOnly import org.jetbrains.jps.builders.BuildTarget import org.jetbrains.jps.builders.storage.BuildDataPaths import org.jetbrains.jps.builders.storage.StorageProvider +import org.jetbrains.jps.incremental.ModuleBuildTarget import org.jetbrains.jps.incremental.storage.BuildDataManager import org.jetbrains.jps.incremental.storage.PathStringDescriptor import org.jetbrains.jps.incremental.storage.StorageOwner @@ -104,7 +105,10 @@ class CacheFormatVersion(targetDataRoot: File) { } } -public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, IncrementalCache { +public class IncrementalCacheImpl( + targetDataRoot: File, + private val target: ModuleBuildTarget +) : StorageOwner, IncrementalCache { companion object { val PROTO_MAP = "proto.tab" val CONSTANTS_MAP = "constants.tab" @@ -143,6 +147,7 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen hasInlineTo) private val cacheFormatVersion = CacheFormatVersion(targetDataRoot) + private val dependents = arrayListOf() private val inlineRegistering = object : InlineRegistering { override fun registerInline(fromPath: String, jvmSignature: String, toPath: String) { @@ -152,6 +157,10 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen override fun getInlineRegistering(): InlineRegistering = inlineRegistering + public fun addDependentCache(cache: IncrementalCacheImpl) { + dependents.add(cache) + } + TestOnly public fun dump(): String { return maps.map { it.dump() }.join("\n\n") @@ -171,6 +180,7 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen public fun getFilesToReinline(): Collection { val result = THashSet(FileUtil.PATH_HASHING_STRATEGY) + val outPath = target?.outputDir!! for ((className, functions) in dirtyInlineFunctionsMap.getEntries()) { val sourceFiles = classToSourcesMap[className] @@ -179,6 +189,14 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen val targetFiles = functions.flatMap { hasInlineTo[sourceFile, it] } result.addAll(targetFiles) } + + val classFile = File(outPath, "${className.internalName}.class") + val classFileName = classFile.normalizedPath + + for (dependent in dependents) { + val targetFiles = functions.flatMap { dependent.hasInlineTo[classFileName, it] } + result.addAll(targetFiles) + } } dirtyInlineFunctionsMap.clean() @@ -724,15 +742,17 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen } } -private val storageProvider = object : StorageProvider() { - override fun createStorage(targetDataDir: File): IncrementalCacheImpl { - return IncrementalCacheImpl(targetDataDir) - } -} - public fun BuildDataPaths.getKotlinCacheVersion(target: BuildTarget<*>): CacheFormatVersion = CacheFormatVersion(getTargetDataRoot(target)) -public fun BuildDataManager.getKotlinCache(target: BuildTarget<*>): IncrementalCacheImpl = getStorage(target, storageProvider) +private data class KotlinIncrementalStorageProvider( + private val target: ModuleBuildTarget +) : StorageProvider() { + override fun createStorage(targetDataDir: File): IncrementalCacheImpl = + IncrementalCacheImpl(targetDataDir, target) +} + +public fun BuildDataManager.getKotlinCache(target: ModuleBuildTarget): IncrementalCacheImpl = + getStorage(target, KotlinIncrementalStorageProvider(target)) private fun ByteArray.md5(): Long { val d = MessageDigest.getInstance("MD5").digest(this)!! diff --git a/jps/jps-plugin/test/org/jetbrains/kotlin/jps/build/AbstractIncrementalJpsTest.kt b/jps/jps-plugin/test/org/jetbrains/kotlin/jps/build/AbstractIncrementalJpsTest.kt index c7cef336e29..2ee2e68ebd0 100644 --- a/jps/jps-plugin/test/org/jetbrains/kotlin/jps/build/AbstractIncrementalJpsTest.kt +++ b/jps/jps-plugin/test/org/jetbrains/kotlin/jps/build/AbstractIncrementalJpsTest.kt @@ -37,6 +37,7 @@ import org.jetbrains.jps.builders.logging.BuildLoggingManager import org.jetbrains.jps.cmdline.ProjectDescriptor import org.jetbrains.jps.incremental.BuilderRegistry import org.jetbrains.jps.incremental.IncProjectBuilder +import org.jetbrains.jps.incremental.ModuleBuildTarget import org.jetbrains.jps.incremental.messages.BuildMessage import org.jetbrains.jps.model.JpsElementFactory import org.jetbrains.jps.model.JpsModuleRootModificationUtil @@ -51,8 +52,7 @@ import org.jetbrains.kotlin.utils.keysToMap import java.io.ByteArrayOutputStream import java.io.File import java.io.PrintStream -import java.util.ArrayList -import java.util.HashMap +import java.util.* import kotlin.properties.Delegates import kotlin.test.assertEquals import kotlin.test.assertFalse @@ -290,7 +290,10 @@ public abstract class AbstractIncrementalJpsTest( private fun createKotlinIncrementalCacheDump(project: ProjectDescriptor): String { return StringBuilder { - for (target in project.buildTargetIndex.allTargets.sortBy { it.presentableName }) { + val allTargets = project.buildTargetIndex.allTargets + val moduleTargets = allTargets.filterIsInstance(ModuleBuildTarget::class.java) + + for (target in moduleTargets.sortedBy { it.presentableName }) { append("\n") append(project.dataManager.getKotlinCache(target).dump()) append("\n\n\n")