Introduce FSOperationsHelper to mark files dirty
This commit is contained in:
@@ -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.builders.storage.BuildDataPaths
|
||||||
import org.jetbrains.jps.incremental.*
|
import org.jetbrains.jps.incremental.*
|
||||||
import org.jetbrains.jps.incremental.ModuleLevelBuilder.ExitCode.*
|
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.java.JavaBuilder
|
||||||
import org.jetbrains.jps.incremental.messages.BuildMessage
|
import org.jetbrains.jps.incremental.messages.BuildMessage
|
||||||
import org.jetbrains.jps.incremental.messages.CompilerMessage
|
import org.jetbrains.jps.incremental.messages.CompilerMessage
|
||||||
@@ -122,10 +121,14 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
|
|||||||
): ModuleLevelBuilder.ExitCode {
|
): ModuleLevelBuilder.ExitCode {
|
||||||
LOG.debug("------------------------------------------")
|
LOG.debug("------------------------------------------")
|
||||||
val messageCollector = MessageCollectorAdapter(context)
|
val messageCollector = MessageCollectorAdapter(context)
|
||||||
|
val fsOperations = FSOperationsHelper(context, chunk)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val exitCode = doBuild(chunk, context, dirtyFilesHolder, messageCollector, outputConsumer)
|
val exitCode = doBuild(chunk, context, dirtyFilesHolder, messageCollector, outputConsumer, fsOperations)
|
||||||
LOG.debug("Build result: " + exitCode)
|
LOG.debug("Build result: " + exitCode)
|
||||||
|
|
||||||
|
if (exitCode == OK && fsOperations.hasMarkedDirty()) return ADDITIONAL_PASS_REQUIRED
|
||||||
|
|
||||||
return exitCode
|
return exitCode
|
||||||
}
|
}
|
||||||
catch (e: StopBuildException) {
|
catch (e: StopBuildException) {
|
||||||
@@ -148,7 +151,9 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
|
|||||||
chunk: ModuleChunk,
|
chunk: ModuleChunk,
|
||||||
context: CompileContext,
|
context: CompileContext,
|
||||||
dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>,
|
dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>,
|
||||||
messageCollector: MessageCollectorAdapter, outputConsumer: ModuleLevelBuilder.OutputConsumer
|
messageCollector: MessageCollectorAdapter,
|
||||||
|
outputConsumer: OutputConsumer,
|
||||||
|
fsOperations: FSOperationsHelper
|
||||||
): ModuleLevelBuilder.ExitCode {
|
): ModuleLevelBuilder.ExitCode {
|
||||||
// Workaround for Android Studio
|
// Workaround for Android Studio
|
||||||
if (!JavaBuilder.IS_ENABLED[context, true] && !JpsUtils.isJsKotlinModule(chunk.representativeTarget())) {
|
if (!JavaBuilder.IS_ENABLED[context, true] && !JpsUtils.isJsKotlinModule(chunk.representativeTarget())) {
|
||||||
@@ -163,9 +168,9 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
|
|||||||
|
|
||||||
if (!isFullRebuild &&
|
if (!isFullRebuild &&
|
||||||
targets.any { hasKotlin(it, dataManager.dataPaths) } &&
|
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
|
val targetsWithDependents = getIncrementalCaches(chunk, context).keys
|
||||||
targetsWithDependents.forEach { clearHasKotlin(it, dataManager.dataPaths) }
|
targetsWithDependents.forEach { clearHasKotlin(it, dataManager.dataPaths) }
|
||||||
return CHUNK_REBUILD_REQUIRED
|
return CHUNK_REBUILD_REQUIRED
|
||||||
@@ -243,53 +248,41 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
|
|||||||
}
|
}
|
||||||
|
|
||||||
val caches = filesToCompile.keySet().map { incrementalCaches[it]!! }
|
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
|
return ADDITIONAL_PASS_REQUIRED
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processChanges(
|
private fun processChanges(
|
||||||
context: CompileContext,
|
|
||||||
chunk: ModuleChunk,
|
|
||||||
compiledFiles: Collection<File>,
|
compiledFiles: Collection<File>,
|
||||||
allCompiledFiles: MutableSet<File>,
|
allCompiledFiles: MutableSet<File>,
|
||||||
dataManager: BuildDataManager,
|
dataManager: BuildDataManager,
|
||||||
caches: List<IncrementalCacheImpl>,
|
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 CompilationResult.doProcessChanges() {
|
||||||
fun isKotlin(file: File) = KotlinSourceFileCollector.isKotlinSourceFile(file)
|
|
||||||
fun isNotCompiled(file: File) = file !in allCompiledFiles
|
|
||||||
|
|
||||||
LOG.debug("compilationResult = $this")
|
LOG.debug("compilationResult = $this")
|
||||||
|
|
||||||
when {
|
when {
|
||||||
inlineAdded -> {
|
inlineAdded -> {
|
||||||
allCompiledFiles.clear()
|
allCompiledFiles.clear()
|
||||||
FSOperations.markDirtyRecursively(context, CompilationRound.NEXT, chunk, ::isKotlin)
|
fsOperations.markChunk(recursively = true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
constantsChanged -> {
|
constantsChanged -> {
|
||||||
FSOperations.markDirtyRecursively(context, CompilationRound.NEXT, chunk, ::isNotCompiled)
|
fsOperations.markChunk(recursively = true, kotlinOnly = false, excludeFiles = allCompiledFiles)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
protoChanged -> {
|
protoChanged -> {
|
||||||
FSOperations.markDirty(context, CompilationRound.NEXT, chunk, { isKotlin(it) && isNotCompiled(it) })
|
fsOperations.markChunk(excludeFiles = allCompiledFiles)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inlineChanged) {
|
if (inlineChanged) {
|
||||||
recompileInlined()
|
for (cache in caches) {
|
||||||
|
fsOperations.markFiles(cache.getFilesToReinline())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,10 +305,7 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
|
|||||||
.toList()
|
.toList()
|
||||||
|
|
||||||
LOG.debug("Mark dirty files: $files")
|
LOG.debug("Mark dirty files: $files")
|
||||||
|
fsOperations.markFiles(files)
|
||||||
files.forEach {
|
|
||||||
FSOperations.markDirty(context, CompilationRound.NEXT, it)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG.debug("End of processing changes")
|
LOG.debug("End of processing changes")
|
||||||
@@ -331,8 +321,12 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun shouldRebuildBecauseVersionChanged(
|
||||||
private fun shouldRebuildBecauseVersionChanged(context: CompileContext, dataManager: BuildDataManager, targets: MutableSet<ModuleBuildTarget>): Boolean {
|
context: CompileContext,
|
||||||
|
dataManager: BuildDataManager,
|
||||||
|
targets: MutableSet<ModuleBuildTarget>,
|
||||||
|
fsOperations: FSOperationsHelper
|
||||||
|
): Boolean {
|
||||||
val cacheVersionsProvider = CacheVersionProvider(dataManager.dataPaths)
|
val cacheVersionsProvider = CacheVersionProvider(dataManager.dataPaths)
|
||||||
val allVersions = cacheVersionsProvider.allVersions(targets)
|
val allVersions = cacheVersionsProvider.allVersions(targets)
|
||||||
val actions = allVersions.map { it.checkVersion() }.toSet().sorted()
|
val actions = allVersions.map { it.checkVersion() }.toSet().sorted()
|
||||||
@@ -348,9 +342,7 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
|
|||||||
|
|
||||||
for (sourceRoot in sourceRoots) {
|
for (sourceRoot in sourceRoots) {
|
||||||
val ktFiles = sourceRoot.file.walk().filter { KotlinSourceFileCollector.isKotlinSourceFile(it) }
|
val ktFiles = sourceRoot.file.walk().filter { KotlinSourceFileCollector.isKotlinSourceFile(it) }
|
||||||
ktFiles.forEach { kt ->
|
fsOperations.markFiles(ktFiles.asIterable())
|
||||||
FSOperations.markDirty(context, CompilationRound.NEXT, kt)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (target in allTargets) {
|
for (target in allTargets) {
|
||||||
|
|||||||
Reference in New Issue
Block a user