Rebuilding dependants fully only when constants/inline functions changed. This is not 100% precise, but it is faster. It is a compromise until we implement preciser incremental compilation.
Original commit: c60797e306
This commit is contained in:
@@ -54,9 +54,12 @@ import org.jetbrains.jps.builders.java.JavaBuilderUtil
|
||||
import com.intellij.util.containers.MultiMap
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||
import org.jetbrains.jps.model.JpsProject
|
||||
import java.io.FileFilter
|
||||
import org.jetbrains.kotlin.jps.incremental.IncrementalCacheImpl.RecompilationDecision.*
|
||||
import org.jetbrains.kotlin.compilerRunner.SimpleOutputItem
|
||||
import org.jetbrains.kotlin.utils.LibraryUtils
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.cache.IncrementalCache
|
||||
import org.jetbrains.jps.incremental.fs.CompilationRound
|
||||
|
||||
public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
|
||||
class object {
|
||||
@@ -133,7 +136,7 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
|
||||
|
||||
val recompilationDecision: IncrementalCacheImpl.RecompilationDecision
|
||||
if (JpsUtils.isJsKotlinModule(chunk.representativeTarget())) {
|
||||
recompilationDecision = IncrementalCacheImpl.RecompilationDecision.DO_NOTHING
|
||||
recompilationDecision = DO_NOTHING
|
||||
}
|
||||
else {
|
||||
recompilationDecision = updateKotlinIncrementalCache(compilationErrors, dirtyFilesHolder, incrementalCaches, outputsItemsAndTargets)
|
||||
@@ -149,15 +152,21 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
|
||||
}
|
||||
|
||||
if (IncrementalCompilation.ENABLED) {
|
||||
if (recompilationDecision == IncrementalCacheImpl.RecompilationDecision.RECOMPILE_ALL) {
|
||||
allCompiledFiles.clear()
|
||||
val targetsCompletelyMarkedDirty = FSOperations.getTargetsCompletelyMarkedDirty(context)
|
||||
FSOperations.markDirtyRecursively(context, chunk)
|
||||
val fileFilter = FileFilter { file ->
|
||||
KotlinSourceFileCollector.isKotlinSourceFile(file) && file !in allCompiledFiles
|
||||
}
|
||||
if (recompilationDecision == IncrementalCacheImpl.RecompilationDecision.COMPILE_OTHERS) {
|
||||
FSOperations.markDirtyRecursively(context, chunk, { file ->
|
||||
KotlinSourceFileCollector.isKotlinSourceFile(file) && file !in allCompiledFiles
|
||||
})
|
||||
|
||||
when (recompilationDecision) {
|
||||
RECOMPILE_ALL_CHUNK_AND_DEPENDANTS -> {
|
||||
allCompiledFiles.clear()
|
||||
FSOperations.markDirtyRecursively(context, chunk)
|
||||
}
|
||||
RECOMPILE_OTHERS_WITH_DEPENDANTS -> {
|
||||
FSOperations.markDirtyRecursively(context, CompilationRound.NEXT, chunk, fileFilter)
|
||||
}
|
||||
RECOMPILE_OTHERS_IN_CHUNK -> {
|
||||
FSOperations.markDirty(context, chunk, fileFilter)
|
||||
}
|
||||
}
|
||||
return ADDITIONAL_PASS_REQUIRED
|
||||
}
|
||||
@@ -254,7 +263,7 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
|
||||
outputsItemsAndTargets: List<Pair<SimpleOutputItem, ModuleBuildTarget>>
|
||||
): IncrementalCacheImpl.RecompilationDecision {
|
||||
if (!IncrementalCompilation.ENABLED) {
|
||||
return IncrementalCacheImpl.RecompilationDecision.DO_NOTHING
|
||||
return DO_NOTHING
|
||||
}
|
||||
|
||||
for ((target, cache) in incrementalCaches) {
|
||||
@@ -265,7 +274,7 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
|
||||
)
|
||||
}
|
||||
|
||||
var recompilationDecision = IncrementalCacheImpl.RecompilationDecision.DO_NOTHING
|
||||
var recompilationDecision = DO_NOTHING
|
||||
for ((outputItem, target) in outputsItemsAndTargets) {
|
||||
val newDecision = incrementalCaches[target]!!.saveFileToCache(outputItem.getSourceFiles(), outputItem.getOutputFile())
|
||||
recompilationDecision = recompilationDecision.merge(newDecision)
|
||||
|
||||
@@ -113,26 +113,38 @@ public class IncrementalCacheImpl(targetDataRoot: File): StorageOwner, Increment
|
||||
val data = BitEncoding.decodeBytes(annotationDataEncoded)
|
||||
when {
|
||||
header.isCompatiblePackageFacadeKind() -> {
|
||||
return if (protoMap.put(className, data)) COMPILE_OTHERS else DO_NOTHING
|
||||
return if (protoMap.put(className, data)) RECOMPILE_OTHERS_IN_CHUNK else DO_NOTHING
|
||||
}
|
||||
header.isCompatibleClassKind() -> {
|
||||
val inlinesChanged = inlineFunctionsMap.process(className, fileBytes)
|
||||
val protoChanged = protoMap.put(className, data)
|
||||
val constantsChanged = constantsMap.process(className, fileBytes)
|
||||
|
||||
return if (inlinesChanged) RECOMPILE_ALL else if (protoChanged || constantsChanged) COMPILE_OTHERS else DO_NOTHING
|
||||
return when {
|
||||
inlinesChanged -> RECOMPILE_ALL_CHUNK_AND_DEPENDANTS
|
||||
constantsChanged -> RECOMPILE_OTHERS_WITH_DEPENDANTS
|
||||
protoChanged -> RECOMPILE_OTHERS_IN_CHUNK
|
||||
else -> DO_NOTHING
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
throw IllegalStateException("Unexpected kind with annotationData: ${header.kind}, isCompatible: ${header.isCompatibleAbiVersion}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (header.syntheticClassKind == JvmAnnotationNames.KotlinSyntheticClass.Kind.PACKAGE_PART) {
|
||||
assert(sourceFiles.size == 1) { "Package part from several source files: $sourceFiles" }
|
||||
|
||||
packagePartMap.putPackagePartSourceData(sourceFiles.first(), className)
|
||||
val inlinesChanged = inlineFunctionsMap.process(className, fileBytes)
|
||||
val constantsChanged = constantsMap.process(className, fileBytes)
|
||||
return if (inlinesChanged) RECOMPILE_ALL else if (constantsChanged) COMPILE_OTHERS else DO_NOTHING
|
||||
|
||||
return when {
|
||||
inlinesChanged -> RECOMPILE_ALL_CHUNK_AND_DEPENDANTS
|
||||
constantsChanged -> RECOMPILE_OTHERS_WITH_DEPENDANTS
|
||||
else -> DO_NOTHING
|
||||
}
|
||||
}
|
||||
|
||||
return DO_NOTHING
|
||||
@@ -497,8 +509,9 @@ public class IncrementalCacheImpl(targetDataRoot: File): StorageOwner, Increment
|
||||
|
||||
enum class RecompilationDecision {
|
||||
DO_NOTHING
|
||||
COMPILE_OTHERS
|
||||
RECOMPILE_ALL
|
||||
RECOMPILE_OTHERS_IN_CHUNK
|
||||
RECOMPILE_OTHERS_WITH_DEPENDANTS
|
||||
RECOMPILE_ALL_CHUNK_AND_DEPENDANTS
|
||||
|
||||
fun merge(other: RecompilationDecision): RecompilationDecision {
|
||||
return if (other.ordinal() > this.ordinal()) other else this
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package c
|
||||
|
||||
fun c() {
|
||||
// This file doesn't use anything from module1, so it won't be recompiled after change
|
||||
}
|
||||
Reference in New Issue
Block a user