jps: improve KotlinDirtySourceFilesHolder

Original commit: 3cfb200e07
This commit is contained in:
Sergey Rostov
2018-06-06 12:09:26 +03:00
parent 60de938f22
commit c01e0935ba
7 changed files with 93 additions and 114 deletions
@@ -976,7 +976,7 @@ open class KotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() {
project.setTestingContext(TestingContext(LookupTracker.DO_NOTHING, object : BuildLogger { project.setTestingContext(TestingContext(LookupTracker.DO_NOTHING, object : BuildLogger {
override fun buildStarted(context: CompileContext, chunk: ModuleChunk) { override fun buildStarted(context: CompileContext, chunk: ModuleChunk) {
actual.append("Targets dependent on ${chunk.targets.joinToString() }:\n") actual.append("Targets dependent on ${chunk.targets.joinToString() }:\n")
actual.append(getDependentTargets(chunk, context).map { it.toString() }.sorted().joinToString("\n")) actual.append(getDependentTargets(chunk.targets, context).map { it.toString() }.sorted().joinToString("\n"))
actual.append("\n---------\n") actual.append("\n---------\n")
} }
@@ -975,7 +975,7 @@ open class KotlinJpsBuildTest : AbstractKotlinJpsBuildTestCase() {
project.setTestingContext(TestingContext(LookupTracker.DO_NOTHING, object : BuildLogger { project.setTestingContext(TestingContext(LookupTracker.DO_NOTHING, object : BuildLogger {
override fun buildStarted(context: CompileContext, chunk: ModuleChunk) { override fun buildStarted(context: CompileContext, chunk: ModuleChunk) {
actual.append("Targets dependent on ${chunk.targets.joinToString() }:\n") actual.append("Targets dependent on ${chunk.targets.joinToString() }:\n")
actual.append(getDependentTargets(chunk, context).map { it.toString() }.sorted().joinToString("\n")) actual.append(getDependentTargets(chunk.targets, context).map { it.toString() }.sorted().joinToString("\n"))
actual.append("\n---------\n") actual.append("\n---------\n")
} }
@@ -23,13 +23,18 @@ import org.jetbrains.jps.builders.BuildTarget
import org.jetbrains.jps.builders.java.dependencyView.Mappings import org.jetbrains.jps.builders.java.dependencyView.Mappings
import org.jetbrains.jps.incremental.CompileContext import org.jetbrains.jps.incremental.CompileContext
import org.jetbrains.jps.incremental.FSOperations import org.jetbrains.jps.incremental.FSOperations
import org.jetbrains.jps.incremental.ModuleBuildTarget
import org.jetbrains.jps.incremental.fs.CompilationRound import org.jetbrains.jps.incremental.fs.CompilationRound
import java.io.File import java.io.File
import java.util.HashMap import java.util.HashMap
/**
* Entry point for safely marking files as dirty.
*/
class FSOperationsHelper( class FSOperationsHelper(
private val compileContext: CompileContext, private val compileContext: CompileContext,
private val chunk: ModuleChunk, private val chunk: ModuleChunk,
private val dirtyFilesHolder: KotlinDirtySourceFilesHolder,
private val log: Logger private val log: Logger
) { ) {
private val moduleBasedFilter = ModulesBasedFileFilter(compileContext, chunk) private val moduleBasedFilter = ModulesBasedFileFilter(compileContext, chunk)
@@ -56,27 +61,46 @@ class FSOperationsHelper(
} }
} }
fun markFilesBeforeInitialRound(files: Iterable<File>) { internal fun markFilesForCurrentRound(files: Iterable<File>) {
markFilesImpl(files, beforeRound = true) { it.exists() && moduleBasedFilter.accept(it) } files.forEach {
val root = compileContext.projectDescriptor.buildRootIndex.findJavaRootDescriptor(compileContext, it)
if (root != null) dirtyFilesHolder.byTarget[root.target]?._markDirty(it)
}
markFilesImpl(files, currentRound = true) { it.exists() && moduleBasedFilter.accept(it) }
}
/**
* Marks given [files] as dirty for current round and given [target] of [chunk].
*/
fun markFilesForCurrentRound(target: ModuleBuildTarget, files: Iterable<File>) {
require(target in chunk.targets)
val targetDirtyFiles = dirtyFilesHolder.byTarget[target]!!
files.forEach {
targetDirtyFiles._markDirty(it)
}
markFilesImpl(files, currentRound = true) { it.exists() }
} }
fun markFiles(files: Iterable<File>) { fun markFiles(files: Iterable<File>) {
markFilesImpl(files, beforeRound = false) { it.exists() } markFilesImpl(files, currentRound = false) { it.exists() }
} }
fun markInChunkOrDependents(files: Iterable<File>, excludeFiles: Set<File>) { fun markInChunkOrDependents(files: Iterable<File>, excludeFiles: Set<File>) {
markFilesImpl(files, beforeRound = false) { it !in excludeFiles && it.exists() && moduleBasedFilter.accept(it) } markFilesImpl(files, currentRound = false) { it !in excludeFiles && it.exists() && moduleBasedFilter.accept(it) }
} }
private inline fun markFilesImpl( private inline fun markFilesImpl(
files: Iterable<File>, files: Iterable<File>,
beforeRound: Boolean, currentRound: Boolean,
shouldMark: (File) -> Boolean shouldMark: (File) -> Boolean
) { ) {
val filesToMark = files.filterTo(HashSet(), shouldMark) val filesToMark = files.filterTo(HashSet(), shouldMark)
if (filesToMark.isEmpty()) return if (filesToMark.isEmpty()) return
val compilationRound = if (beforeRound) { val compilationRound = if (currentRound) {
buildLogger?.markedAsDirtyBeforeRound(filesToMark) buildLogger?.markedAsDirtyBeforeRound(filesToMark)
CompilationRound.CURRENT CompilationRound.CURRENT
} else { } else {
@@ -118,7 +118,16 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
if (targets.none { hasKotlin[it] == true }) return if (targets.none { hasKotlin[it] == true }) return
val fsOperations = FSOperationsHelper(context, chunk, LOG) val roundDirtyFiles = KotlinDirtySourceFilesHolder(
chunk,
context,
object : DirtyFilesHolderBase<JavaSourceRootDescriptor, ModuleBuildTarget>(context) {
override fun processDirtyFiles(processor: FileProcessor<JavaSourceRootDescriptor, ModuleBuildTarget>) {
FSOperations.processFilesToRecompile(context, chunk, processor)
}
}
)
val fsOperations = FSOperationsHelper(context, chunk, roundDirtyFiles, LOG)
if (System.getProperty(SKIP_CACHE_VERSION_CHECK_PROPERTY) == null) { if (System.getProperty(SKIP_CACHE_VERSION_CHECK_PROPERTY) == null) {
val cacheVersionsProvider = CacheVersionProvider(dataManager.dataPaths) val cacheVersionsProvider = CacheVersionProvider(dataManager.dataPaths)
@@ -142,25 +151,16 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
return return
} }
markAdditionalFilesForInitialRound(chunk, context, fsOperations) markAdditionalFilesForInitialRound(chunk, context, fsOperations, roundDirtyFiles)
buildLogger?.afterBuildStarted(context, chunk) buildLogger?.afterBuildStarted(context, chunk)
} }
private fun markAdditionalFilesForInitialRound( private fun markAdditionalFilesForInitialRound(
chunk: ModuleChunk, chunk: ModuleChunk,
context: CompileContext, context: CompileContext,
fsOperations: FSOperationsHelper fsOperations: FSOperationsHelper,
dirtyFilesHolder: KotlinDirtySourceFilesHolder
) { ) {
val roundDirtyFiles = KotlinDirtySourceFilesHolder(
chunk,
context,
fsOperations,
object : DirtyFilesHolderBase<JavaSourceRootDescriptor, ModuleBuildTarget>(context) {
override fun processDirtyFiles(processor: FileProcessor<JavaSourceRootDescriptor, ModuleBuildTarget>) {
FSOperations.processFilesToRecompile(context, chunk, processor)
}
}
)
val representativeTarget = context.kotlinBuildTargets[chunk.representativeTarget()] ?: return val representativeTarget = context.kotlinBuildTargets[chunk.representativeTarget()] ?: return
val incrementalCaches = getIncrementalCaches(chunk, context) val incrementalCaches = getIncrementalCaches(chunk, context)
@@ -177,8 +177,8 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
val removedClasses = HashSet<String>() val removedClasses = HashSet<String>()
for (target in chunk.targets) { for (target in chunk.targets) {
val cache = incrementalCaches[target] ?: continue val cache = incrementalCaches[target] ?: continue
val dirtyFiles = roundDirtyFiles.getDirtyFiles(target) val dirtyFiles = dirtyFilesHolder.getDirtyFiles(target)
val removedFiles = roundDirtyFiles.getRemovedFilesSet(target) val removedFiles = dirtyFilesHolder.getRemovedFiles(target)
val existingClasses = JpsKotlinCompilerRunner().classesFqNamesByFiles(environment, dirtyFiles) val existingClasses = JpsKotlinCompilerRunner().classesFqNamesByFiles(environment, dirtyFiles)
val previousClasses = cache.classesFqNamesBySources(dirtyFiles + removedFiles) val previousClasses = cache.classesFqNamesBySources(dirtyFiles + removedFiles)
@@ -194,7 +194,7 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
removedClasses.forEach { changesCollector.collectSignature(FqName(it), areSubclassesAffected = true) } removedClasses.forEach { changesCollector.collectSignature(FqName(it), areSubclassesAffected = true) }
val affectedByRemovedClasses = changesCollector.getDirtyFiles(incrementalCaches.values, context.projectDescriptor.dataManager) val affectedByRemovedClasses = changesCollector.getDirtyFiles(incrementalCaches.values, context.projectDescriptor.dataManager)
fsOperations.markFilesBeforeInitialRound(affectedByRemovedClasses) fsOperations.markFilesForCurrentRound(affectedByRemovedClasses)
} }
private fun checkCachesVersions( private fun checkCachesVersions(
@@ -234,10 +234,11 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
val kotlinTarget = context.kotlinBuildTargets[chunk.representativeTarget()] ?: return OK val kotlinTarget = context.kotlinBuildTargets[chunk.representativeTarget()] ?: return OK
val messageCollector = MessageCollectorAdapter(context, kotlinTarget) val messageCollector = MessageCollectorAdapter(context, kotlinTarget)
val fsOperations = FSOperationsHelper(context, chunk, LOG) val kotlinDirtyFilesHolder = KotlinDirtySourceFilesHolder(chunk, context, dirtyFilesHolder)
val fsOperations = FSOperationsHelper(context, chunk, kotlinDirtyFilesHolder, LOG)
try { try {
val proposedExitCode = doBuild(chunk, kotlinTarget, context, dirtyFilesHolder, messageCollector, outputConsumer, fsOperations) val proposedExitCode = doBuild(chunk, kotlinTarget, context, kotlinDirtyFilesHolder, messageCollector, outputConsumer, fsOperations)
val actualExitCode = if (proposedExitCode == OK && fsOperations.hasMarkedDirty) ADDITIONAL_PASS_REQUIRED else proposedExitCode val actualExitCode = if (proposedExitCode == OK && fsOperations.hasMarkedDirty) ADDITIONAL_PASS_REQUIRED else proposedExitCode
@@ -260,7 +261,7 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
chunk: ModuleChunk, chunk: ModuleChunk,
representativeTarget: KotlinModuleBuildTarget, representativeTarget: KotlinModuleBuildTarget,
context: CompileContext, context: CompileContext,
dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>, kotlinDirtyFilesHolder: KotlinDirtySourceFilesHolder,
messageCollector: MessageCollectorAdapter, messageCollector: MessageCollectorAdapter,
outputConsumer: OutputConsumer, outputConsumer: OutputConsumer,
fsOperations: FSOperationsHelper fsOperations: FSOperationsHelper
@@ -271,7 +272,6 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
return NOTHING_DONE return NOTHING_DONE
} }
val roundDirtyFilesHolder = KotlinDirtySourceFilesHolder(chunk, context, fsOperations, dirtyFilesHolder)
val projectDescriptor = context.projectDescriptor val projectDescriptor = context.projectDescriptor
val dataManager = projectDescriptor.dataManager val dataManager = projectDescriptor.dataManager
val targets = chunk.targets val targets = chunk.targets
@@ -280,7 +280,7 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
val isChunkRebuilding = JavaBuilderUtil.isForcedRecompilationAllJavaModules(context) val isChunkRebuilding = JavaBuilderUtil.isForcedRecompilationAllJavaModules(context)
|| targets.any { rebuildAfterCacheVersionChanged[it] == true } || targets.any { rebuildAfterCacheVersionChanged[it] == true }
if (roundDirtyFilesHolder.hasDirtyOrRemovedFiles) { if (kotlinDirtyFilesHolder.hasDirtyOrRemovedFiles) {
if (!isChunkRebuilding && !IncrementalCompilation.isEnabled()) { if (!isChunkRebuilding && !IncrementalCompilation.isEnabled()) {
targets.forEach { rebuildAfterCacheVersionChanged[it] = true } targets.forEach { rebuildAfterCacheVersionChanged[it] = true }
return CHUNK_REBUILD_REQUIRED return CHUNK_REBUILD_REQUIRED
@@ -319,13 +319,13 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
} }
if (LOG.isDebugEnabled) { if (LOG.isDebugEnabled) {
LOG.debug("Compiling files: ${roundDirtyFilesHolder.dirtyFiles}") LOG.debug("Compiling files: ${kotlinDirtyFilesHolder.allDirtyFiles}")
} }
val start = System.nanoTime() val start = System.nanoTime()
val outputItemCollector = doCompileModuleChunk( val outputItemCollector = doCompileModuleChunk(
chunk, representativeTarget, commonArguments, context, roundDirtyFilesHolder, environment, chunk, representativeTarget, commonArguments, context, kotlinDirtyFilesHolder, fsOperations,
incrementalCaches environment, incrementalCaches
) )
statisticsLogger.registerStatistic(chunk, System.nanoTime() - start) statisticsLogger.registerStatistic(chunk, System.nanoTime() - start)
@@ -348,7 +348,7 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
saveVersions(context, chunk, commonArguments) saveVersions(context, chunk, commonArguments)
if (targets.any { hasKotlin[it] == null }) { if (targets.any { hasKotlin[it] == null }) {
fsOperations.markChunk(recursively = false, kotlinOnly = true, excludeFiles = roundDirtyFilesHolder.dirtyFiles) fsOperations.markChunk(recursively = false, kotlinOnly = true, excludeFiles = kotlinDirtyFilesHolder.allDirtyFiles)
} }
for (target in targets) { for (target in targets) {
@@ -362,7 +362,7 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
representativeTarget.updateChunkMappings( representativeTarget.updateChunkMappings(
chunk, chunk,
roundDirtyFilesHolder, kotlinDirtyFilesHolder,
generatedFiles, generatedFiles,
incrementalCaches incrementalCaches
) )
@@ -383,11 +383,11 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
kotlinModuleBuilderTarget.updateCaches(incrementalCaches[target]!!, files, changesCollector, environment) kotlinModuleBuilderTarget.updateCaches(incrementalCaches[target]!!, files, changesCollector, environment)
} }
updateLookupStorage(lookupTracker, dataManager, roundDirtyFilesHolder) updateLookupStorage(lookupTracker, dataManager, kotlinDirtyFilesHolder)
if (!isChunkRebuilding) { if (!isChunkRebuilding) {
changesCollector.processChangesUsingLookups( changesCollector.processChangesUsingLookups(
roundDirtyFilesHolder.dirtyFiles, kotlinDirtyFilesHolder.allDirtyFiles,
dataManager, dataManager,
fsOperations, fsOperations,
incrementalCaches.values incrementalCaches.values
@@ -499,6 +499,7 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
commonArguments: CommonCompilerArguments, commonArguments: CommonCompilerArguments,
context: CompileContext, context: CompileContext,
dirtyFilesHolder: KotlinDirtySourceFilesHolder, dirtyFilesHolder: KotlinDirtySourceFilesHolder,
fsOperations: FSOperationsHelper,
environment: JpsCompilerEnvironment, environment: JpsCompilerEnvironment,
incrementalCaches: Map<ModuleBuildTarget, JpsIncrementalCache> incrementalCaches: Map<ModuleBuildTarget, JpsIncrementalCache>
): OutputItemsCollector? { ): OutputItemsCollector? {
@@ -528,15 +529,10 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
val targetDirtyFiles = dirtyFilesHolder.byTarget[target] val targetDirtyFiles = dirtyFilesHolder.byTarget[target]
if (cache != null && targetDirtyFiles != null) { if (cache != null && targetDirtyFiles != null) {
val removedAndDirtyFiles: MutableSet<File> = mutableSetOf() val complementaryFiles = cache.clearComplementaryFilesMapping(targetDirtyFiles.dirty + targetDirtyFiles.removed)
fsOperations.markFilesForCurrentRound(target, complementaryFiles)
removedAndDirtyFiles.addAll(dirtyFilesHolder.getDirtyFiles(target)) cache.markDirty(targetDirtyFiles.dirty + targetDirtyFiles.removed)
removedAndDirtyFiles.addAll(dirtyFilesHolder.getRemovedFilesSet(target))
val complementaryFiles = cache.clearComplementaryFilesMapping(targetDirtyFiles.dirtyOrRemovedFiles)
targetDirtyFiles.markDirtyForCurrentRound(complementaryFiles)
cache.markDirty(targetDirtyFiles.dirtyOrRemovedFiles)
} }
} }
} }
@@ -644,7 +640,7 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
throw AssertionError("Lookup tracker is expected to be LookupTrackerImpl, got ${lookupTracker::class.java}") throw AssertionError("Lookup tracker is expected to be LookupTrackerImpl, got ${lookupTracker::class.java}")
dataManager.withLookupStorage { lookupStorage -> dataManager.withLookupStorage { lookupStorage ->
lookupStorage.removeLookupsFrom(dirtyFilesHolder.dirtyOrRemovedFilesSet.asSequence()) lookupStorage.removeLookupsFrom(dirtyFilesHolder.allDirtyFiles.asSequence() + dirtyFilesHolder.allRemovedFilesFiles.asSequence())
lookupStorage.addAll(lookupTracker.lookups.entrySet(), lookupTracker.pathInterner.values) lookupStorage.addAll(lookupTracker.lookups.entrySet(), lookupTracker.pathInterner.values)
} }
} }
@@ -19,8 +19,6 @@ package org.jetbrains.kotlin.jps.build
import com.intellij.openapi.util.io.FileUtilRt import com.intellij.openapi.util.io.FileUtilRt
import org.jetbrains.jps.ModuleChunk import org.jetbrains.jps.ModuleChunk
import org.jetbrains.jps.builders.DirtyFilesHolder import org.jetbrains.jps.builders.DirtyFilesHolder
import org.jetbrains.jps.builders.FileProcessor
import org.jetbrains.jps.builders.impl.DirtyFilesHolderBase
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor
import org.jetbrains.jps.incremental.CompileContext import org.jetbrains.jps.incremental.CompileContext
import org.jetbrains.jps.incremental.ModuleBuildTarget import org.jetbrains.jps.incremental.ModuleBuildTarget
@@ -30,59 +28,44 @@ import java.io.File
* Holding kotlin dirty files list for particular build round. * Holding kotlin dirty files list for particular build round.
* Dirty and removed files set are initialized from [delegate]. * Dirty and removed files set are initialized from [delegate].
* *
* Probably should be merged with [FSOperationsHelper] * Additional dirty files should be added only through [FSOperationsHelper.markFilesForCurrentRound]
*/ */
class KotlinDirtySourceFilesHolder( class KotlinDirtySourceFilesHolder(
val chunk: ModuleChunk, val chunk: ModuleChunk,
val context: CompileContext, val context: CompileContext,
val fsOperations: FSOperationsHelper,
delegate: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> delegate: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>
) : DirtyFilesHolderBase<JavaSourceRootDescriptor, ModuleBuildTarget>(context) { ) {
val byTarget: Map<ModuleBuildTarget, TargetFiles> val byTarget: Map<ModuleBuildTarget, TargetFiles>
inner class TargetFiles(val target: ModuleBuildTarget, val removed: Collection<String>) { inner class TargetFiles(val target: ModuleBuildTarget, val removed: Collection<File>) {
val dirty: MutableSet<DirtyFile> = mutableSetOf() private val _dirty: MutableSet<File> = mutableSetOf()
val dirtyOrRemovedFiles: Set<File> val dirty: Set<File>
get() { get() = _dirty
val result = mutableSetOf<File>()
dirty.forEach { result.add(it.file) }
removed.forEach { result.add(File(it)) }
return result
}
fun markDirtyForCurrentRound(files: Collection<File>) { /**
fsOperations.markFilesBeforeInitialRound(files) * Should be called only from [FSOperationsHelper.markFilesForCurrentRound]
files.forEach { * and during KotlinDirtySourceFilesHolder initialization.
dirty.add(DirtyFile(it, null)) */
} internal fun _markDirty(file: File) {
_dirty.add(file)
} }
} }
data class DirtyFile(val file: File, val root: JavaSourceRootDescriptor?)
val hasRemovedFiles: Boolean val hasRemovedFiles: Boolean
get() = byTarget.any { it.value.removed.isNotEmpty() }
override fun hasRemovedFiles(): Boolean = hasRemovedFiles
val hasDirtyFiles: Boolean val hasDirtyFiles: Boolean
get() = byTarget.any { it.value.dirty.isNotEmpty() }
override fun hasDirtyFiles(): Boolean = hasDirtyFiles
val hasDirtyOrRemovedFiles: Boolean val hasDirtyOrRemovedFiles: Boolean
get() = hasRemovedFiles || hasDirtyFiles get() = hasRemovedFiles || hasDirtyFiles
init { init {
val byTarget = mutableMapOf<ModuleBuildTarget, TargetFiles>() val byTarget = mutableMapOf<ModuleBuildTarget, TargetFiles>()
var hasDirtyFiles = false
var hasRemovedFiles = false
chunk.targets.forEach { target -> chunk.targets.forEach { target ->
val removedFiles = delegate.getRemovedFiles(target) val removedFiles = delegate.getRemovedFiles(target).map { File(it) }
if (removedFiles.isNotEmpty()) {
hasRemovedFiles = true
}
byTarget[target] = TargetFiles(target, removedFiles) byTarget[target] = TargetFiles(target, removedFiles)
} }
@@ -91,50 +74,26 @@ class KotlinDirtySourceFilesHolder(
?: error("processDirtyFiles should callback only on chunk `$chunk` targets (`$target` is not)") ?: error("processDirtyFiles should callback only on chunk `$chunk` targets (`$target` is not)")
if (file.isKotlinSourceFile) { if (file.isKotlinSourceFile) {
targetInfo.dirty.add(DirtyFile(file, root)) targetInfo._markDirty(file)
hasDirtyFiles = true
} }
true true
} }
this.byTarget = byTarget this.byTarget = byTarget
this.hasRemovedFiles = hasRemovedFiles
this.hasDirtyFiles = hasDirtyFiles
}
override fun processDirtyFiles(processor: FileProcessor<JavaSourceRootDescriptor, ModuleBuildTarget>) {
for ((target, info) in byTarget) {
info.dirty.forEach {
if (!processor.apply(target, it.file, it.root)) return
}
}
} }
fun getDirtyFiles(target: ModuleBuildTarget): Set<File> = fun getDirtyFiles(target: ModuleBuildTarget): Set<File> =
byTarget[target]?.dirty?.mapTo(mutableSetOf()) { it.file } ?: setOf() byTarget[target]?.dirty ?: setOf()
fun getRemovedFilesSet(target: ModuleBuildTarget): Set<File> = fun getRemovedFiles(target: ModuleBuildTarget): Collection<File> =
byTarget[target]?.removed?.mapTo(mutableSetOf()) { File(it) } ?: setOf() byTarget[target]?.removed ?: listOf()
override fun getRemovedFiles(target: ModuleBuildTarget): Collection<String> = val allDirtyFiles: Set<File>
byTarget.flatMap { it.value.removed } get() = byTarget.flatMapTo(mutableSetOf()) { it.value.dirty }
val removedFilesCount val allRemovedFilesFiles
get() = byTarget.values.flatMapTo(mutableSetOf()) { it.removed }.size get() = byTarget.flatMapTo(mutableSetOf()) { it.value.removed }
val dirtyFiles: Set<File>
get() = byTarget.flatMapTo(mutableSetOf()) { it.value.dirty.map { it.file } }
val dirtyOrRemovedFilesSet: Set<File>
get() {
val result = mutableSetOf<File>()
byTarget.forEach {
it.value.dirty.forEach { result.add(it.file) }
it.value.removed.forEach { result.add(File(it)) }
}
return result
}
} }
val File.isKotlinSourceFile: Boolean val File.isKotlinSourceFile: Boolean
@@ -17,7 +17,7 @@ import java.io.File
class MessageCollectorAdapter( class MessageCollectorAdapter(
private val context: CompileContext, private val context: CompileContext,
val kotlinTarget: KotlinModuleBuildTarget? private val kotlinTarget: KotlinModuleBuildTarget?
) : MessageCollector { ) : MessageCollector {
private var hasErrors = false private var hasErrors = false
@@ -133,7 +133,7 @@ class KotlinJvmModuleBuildTarget(compileContext: CompileContext, jpsModuleBuildT
) )
} }
val filesSet = dirtyFilesHolder.dirtyFiles val filesSet = dirtyFilesHolder.allDirtyFiles
val moduleFile = generateModuleDescription(chunk, dirtyFilesHolder) val moduleFile = generateModuleDescription(chunk, dirtyFilesHolder)
if (moduleFile == null) { if (moduleFile == null) {
@@ -150,7 +150,7 @@ class KotlinJvmModuleBuildTarget(compileContext: CompileContext, jpsModuleBuildT
val module = chunk.representativeTarget().module val module = chunk.representativeTarget().module
if (KotlinBuilder.LOG.isDebugEnabled) { if (KotlinBuilder.LOG.isDebugEnabled) {
val totalRemovedFiles = dirtyFilesHolder.removedFilesCount val totalRemovedFiles = dirtyFilesHolder.allRemovedFilesFiles.size
KotlinBuilder.LOG.debug("Compiling to JVM ${filesSet.size} files" KotlinBuilder.LOG.debug("Compiling to JVM ${filesSet.size} files"
+ (if (totalRemovedFiles == 0) "" else " ($totalRemovedFiles removed files)") + (if (totalRemovedFiles == 0) "" else " ($totalRemovedFiles removed files)")
+ " in " + chunk.targets.joinToString { it.presentableName }) + " in " + chunk.targets.joinToString { it.presentableName })
@@ -303,7 +303,7 @@ class KotlinJvmModuleBuildTarget(compileContext: CompileContext, jpsModuleBuildT
val targetDirtyFiles: Map<ModuleBuildTarget, Set<File>> = chunk.targets.keysToMap { val targetDirtyFiles: Map<ModuleBuildTarget, Set<File>> = chunk.targets.keysToMap {
val files = HashSet<File>() val files = HashSet<File>()
dirtyFilesHolder.getRemovedFiles(it).mapTo(files, ::File) files.addAll(dirtyFilesHolder.getRemovedFiles(it))
files.addAll(dirtyFilesHolder.getDirtyFiles(it)) files.addAll(dirtyFilesHolder.getDirtyFiles(it))
files files
} }
@@ -336,7 +336,7 @@ class KotlinJvmModuleBuildTarget(compileContext: CompileContext, jpsModuleBuildT
} }
} }
val allCompiled = dirtyFilesHolder.dirtyFiles val allCompiled = dirtyFilesHolder.allDirtyFiles
JavaBuilderUtil.registerFilesToCompile(context, allCompiled) JavaBuilderUtil.registerFilesToCompile(context, allCompiled)
JavaBuilderUtil.registerSuccessfullyCompiled(context, allCompiled) JavaBuilderUtil.registerSuccessfullyCompiled(context, allCompiled)
} }