Introduce FSOperationsHelper to mark files dirty

This commit is contained in:
Alexey Tsvetkov
2015-12-01 11:33:14 +03:00
parent 98e0905eb3
commit 87f09ab5b0
2 changed files with 83 additions and 35 deletions
@@ -0,0 +1,56 @@
/*
* Copyright 2010-2015 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.jps.build
import org.jetbrains.jps.ModuleChunk
import org.jetbrains.jps.incremental.CompileContext
import org.jetbrains.jps.incremental.FSOperations
import org.jetbrains.jps.incremental.fs.CompilationRound
import java.io.File
class FSOperationsHelper(private val compileContext: CompileContext, private val chunk: ModuleChunk) {
private var markedDirty = false
fun hasMarkedDirty(): Boolean = markedDirty
fun markChunk(recursively: Boolean = false, kotlinOnly: Boolean = true, excludeFiles: Set<File> = setOf()) {
fun shouldMark(file: File): Boolean {
if (kotlinOnly && !KotlinSourceFileCollector.isKotlinSourceFile(file)) return false
if (file in excludeFiles) return false
markedDirty = true
return true
}
if (recursively) {
FSOperations.markDirtyRecursively(compileContext, CompilationRound.NEXT, chunk, ::shouldMark)
}
else {
FSOperations.markDirty(compileContext, CompilationRound.NEXT, chunk, ::shouldMark)
}
}
fun markFiles(files: Iterable<File>, excludeFiles: Set<File> = setOf()) {
for (file in files) {
if (file in excludeFiles || !file.exists()) continue
FSOperations.markDirty(compileContext, CompilationRound.NEXT, file)
markedDirty = true
}
}
}
@@ -32,7 +32,6 @@ import org.jetbrains.jps.builders.java.dependencyView.Mappings
import org.jetbrains.jps.builders.storage.BuildDataPaths
import org.jetbrains.jps.incremental.*
import org.jetbrains.jps.incremental.ModuleLevelBuilder.ExitCode.*
import org.jetbrains.jps.incremental.fs.CompilationRound
import org.jetbrains.jps.incremental.java.JavaBuilder
import org.jetbrains.jps.incremental.messages.BuildMessage
import org.jetbrains.jps.incremental.messages.CompilerMessage
@@ -122,10 +121,14 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
): ModuleLevelBuilder.ExitCode {
LOG.debug("------------------------------------------")
val messageCollector = MessageCollectorAdapter(context)
val fsOperations = FSOperationsHelper(context, chunk)
try {
val exitCode = doBuild(chunk, context, dirtyFilesHolder, messageCollector, outputConsumer)
val exitCode = doBuild(chunk, context, dirtyFilesHolder, messageCollector, outputConsumer, fsOperations)
LOG.debug("Build result: " + exitCode)
if (exitCode == OK && fsOperations.hasMarkedDirty()) return ADDITIONAL_PASS_REQUIRED
return exitCode
}
catch (e: StopBuildException) {
@@ -148,7 +151,9 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
chunk: ModuleChunk,
context: CompileContext,
dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>,
messageCollector: MessageCollectorAdapter, outputConsumer: ModuleLevelBuilder.OutputConsumer
messageCollector: MessageCollectorAdapter,
outputConsumer: OutputConsumer,
fsOperations: FSOperationsHelper
): ModuleLevelBuilder.ExitCode {
// Workaround for Android Studio
if (!JavaBuilder.IS_ENABLED[context, true] && !JpsUtils.isJsKotlinModule(chunk.representativeTarget())) {
@@ -163,9 +168,9 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
if (!isFullRebuild &&
targets.any { hasKotlin(it, dataManager.dataPaths) } &&
shouldRebuildBecauseVersionChanged(context, dataManager, targets)
shouldRebuildBecauseVersionChanged(context, dataManager, targets, fsOperations)
) {
FSOperations.markDirtyRecursively(context, CompilationRound.NEXT, chunk) { KotlinSourceFileCollector.isKotlinSourceFile(it) }
fsOperations.markChunk(recursively = true)
val targetsWithDependents = getIncrementalCaches(chunk, context).keys
targetsWithDependents.forEach { clearHasKotlin(it, dataManager.dataPaths) }
return CHUNK_REBUILD_REQUIRED
@@ -243,53 +248,41 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
}
val caches = filesToCompile.keySet().map { incrementalCaches[it]!! }
processChanges(context, chunk, filesToCompile.values(), allCompiledFiles, dataManager, caches, changesInfo)
processChanges(filesToCompile.values(), allCompiledFiles, dataManager, caches, changesInfo, fsOperations)
return ADDITIONAL_PASS_REQUIRED
}
private fun processChanges(
context: CompileContext,
chunk: ModuleChunk,
compiledFiles: Collection<File>,
allCompiledFiles: MutableSet<File>,
dataManager: BuildDataManager,
caches: List<IncrementalCacheImpl>,
compilationResult: CompilationResult
compilationResult: CompilationResult,
fsOperations: FSOperationsHelper
) {
fun recompileInlined() {
for (cache in caches) {
val filesToReinline = cache.getFilesToReinline()
filesToReinline.forEach {
FSOperations.markDirty(context, CompilationRound.NEXT, it)
}
}
}
fun CompilationResult.doProcessChanges() {
fun isKotlin(file: File) = KotlinSourceFileCollector.isKotlinSourceFile(file)
fun isNotCompiled(file: File) = file !in allCompiledFiles
LOG.debug("compilationResult = $this")
when {
inlineAdded -> {
allCompiledFiles.clear()
FSOperations.markDirtyRecursively(context, CompilationRound.NEXT, chunk, ::isKotlin)
fsOperations.markChunk(recursively = true)
return
}
constantsChanged -> {
FSOperations.markDirtyRecursively(context, CompilationRound.NEXT, chunk, ::isNotCompiled)
fsOperations.markChunk(recursively = true, kotlinOnly = false, excludeFiles = allCompiledFiles)
return
}
protoChanged -> {
FSOperations.markDirty(context, CompilationRound.NEXT, chunk, { isKotlin(it) && isNotCompiled(it) })
fsOperations.markChunk(excludeFiles = allCompiledFiles)
}
}
if (inlineChanged) {
recompileInlined()
for (cache in caches) {
fsOperations.markFiles(cache.getFilesToReinline())
}
}
}
@@ -312,10 +305,7 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
.toList()
LOG.debug("Mark dirty files: $files")
files.forEach {
FSOperations.markDirty(context, CompilationRound.NEXT, it)
}
fsOperations.markFiles(files)
}
LOG.debug("End of processing changes")
@@ -331,8 +321,12 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
}
}
private fun shouldRebuildBecauseVersionChanged(context: CompileContext, dataManager: BuildDataManager, targets: MutableSet<ModuleBuildTarget>): Boolean {
private fun shouldRebuildBecauseVersionChanged(
context: CompileContext,
dataManager: BuildDataManager,
targets: MutableSet<ModuleBuildTarget>,
fsOperations: FSOperationsHelper
): Boolean {
val cacheVersionsProvider = CacheVersionProvider(dataManager.dataPaths)
val allVersions = cacheVersionsProvider.allVersions(targets)
val actions = allVersions.map { it.checkVersion() }.toSet().sorted()
@@ -348,9 +342,7 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
for (sourceRoot in sourceRoots) {
val ktFiles = sourceRoot.file.walk().filter { KotlinSourceFileCollector.isKotlinSourceFile(it) }
ktFiles.forEach { kt ->
FSOperations.markDirty(context, CompilationRound.NEXT, kt)
}
fsOperations.markFiles(ktFiles.asIterable())
}
for (target in allTargets) {