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.
This commit is contained in:
@@ -54,9 +54,12 @@ import org.jetbrains.jps.builders.java.JavaBuilderUtil
|
|||||||
import com.intellij.util.containers.MultiMap
|
import com.intellij.util.containers.MultiMap
|
||||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||||
import org.jetbrains.jps.model.JpsProject
|
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.compilerRunner.SimpleOutputItem
|
||||||
import org.jetbrains.kotlin.utils.LibraryUtils
|
import org.jetbrains.kotlin.utils.LibraryUtils
|
||||||
import org.jetbrains.kotlin.load.kotlin.incremental.cache.IncrementalCache
|
import org.jetbrains.kotlin.load.kotlin.incremental.cache.IncrementalCache
|
||||||
|
import org.jetbrains.jps.incremental.fs.CompilationRound
|
||||||
|
|
||||||
public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
|
public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
|
||||||
class object {
|
class object {
|
||||||
@@ -133,7 +136,7 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
|
|||||||
|
|
||||||
val recompilationDecision: IncrementalCacheImpl.RecompilationDecision
|
val recompilationDecision: IncrementalCacheImpl.RecompilationDecision
|
||||||
if (JpsUtils.isJsKotlinModule(chunk.representativeTarget())) {
|
if (JpsUtils.isJsKotlinModule(chunk.representativeTarget())) {
|
||||||
recompilationDecision = IncrementalCacheImpl.RecompilationDecision.DO_NOTHING
|
recompilationDecision = DO_NOTHING
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
recompilationDecision = updateKotlinIncrementalCache(compilationErrors, dirtyFilesHolder, incrementalCaches, outputsItemsAndTargets)
|
recompilationDecision = updateKotlinIncrementalCache(compilationErrors, dirtyFilesHolder, incrementalCaches, outputsItemsAndTargets)
|
||||||
@@ -149,15 +152,21 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (IncrementalCompilation.ENABLED) {
|
if (IncrementalCompilation.ENABLED) {
|
||||||
if (recompilationDecision == IncrementalCacheImpl.RecompilationDecision.RECOMPILE_ALL) {
|
val fileFilter = FileFilter { file ->
|
||||||
allCompiledFiles.clear()
|
KotlinSourceFileCollector.isKotlinSourceFile(file) && file !in allCompiledFiles
|
||||||
val targetsCompletelyMarkedDirty = FSOperations.getTargetsCompletelyMarkedDirty(context)
|
|
||||||
FSOperations.markDirtyRecursively(context, chunk)
|
|
||||||
}
|
}
|
||||||
if (recompilationDecision == IncrementalCacheImpl.RecompilationDecision.COMPILE_OTHERS) {
|
|
||||||
FSOperations.markDirtyRecursively(context, chunk, { file ->
|
when (recompilationDecision) {
|
||||||
KotlinSourceFileCollector.isKotlinSourceFile(file) && file !in allCompiledFiles
|
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
|
return ADDITIONAL_PASS_REQUIRED
|
||||||
}
|
}
|
||||||
@@ -254,7 +263,7 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
|
|||||||
outputsItemsAndTargets: List<Pair<SimpleOutputItem, ModuleBuildTarget>>
|
outputsItemsAndTargets: List<Pair<SimpleOutputItem, ModuleBuildTarget>>
|
||||||
): IncrementalCacheImpl.RecompilationDecision {
|
): IncrementalCacheImpl.RecompilationDecision {
|
||||||
if (!IncrementalCompilation.ENABLED) {
|
if (!IncrementalCompilation.ENABLED) {
|
||||||
return IncrementalCacheImpl.RecompilationDecision.DO_NOTHING
|
return DO_NOTHING
|
||||||
}
|
}
|
||||||
|
|
||||||
for ((target, cache) in incrementalCaches) {
|
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) {
|
for ((outputItem, target) in outputsItemsAndTargets) {
|
||||||
val newDecision = incrementalCaches[target]!!.saveFileToCache(outputItem.getSourceFiles(), outputItem.getOutputFile())
|
val newDecision = incrementalCaches[target]!!.saveFileToCache(outputItem.getSourceFiles(), outputItem.getOutputFile())
|
||||||
recompilationDecision = recompilationDecision.merge(newDecision)
|
recompilationDecision = recompilationDecision.merge(newDecision)
|
||||||
|
|||||||
@@ -113,26 +113,38 @@ public class IncrementalCacheImpl(targetDataRoot: File): StorageOwner, Increment
|
|||||||
val data = BitEncoding.decodeBytes(annotationDataEncoded)
|
val data = BitEncoding.decodeBytes(annotationDataEncoded)
|
||||||
when {
|
when {
|
||||||
header.isCompatiblePackageFacadeKind() -> {
|
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() -> {
|
header.isCompatibleClassKind() -> {
|
||||||
val inlinesChanged = inlineFunctionsMap.process(className, fileBytes)
|
val inlinesChanged = inlineFunctionsMap.process(className, fileBytes)
|
||||||
val protoChanged = protoMap.put(className, data)
|
val protoChanged = protoMap.put(className, data)
|
||||||
val constantsChanged = constantsMap.process(className, fileBytes)
|
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 -> {
|
else -> {
|
||||||
throw IllegalStateException("Unexpected kind with annotationData: ${header.kind}, isCompatible: ${header.isCompatibleAbiVersion}")
|
throw IllegalStateException("Unexpected kind with annotationData: ${header.kind}, isCompatible: ${header.isCompatibleAbiVersion}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.syntheticClassKind == JvmAnnotationNames.KotlinSyntheticClass.Kind.PACKAGE_PART) {
|
if (header.syntheticClassKind == JvmAnnotationNames.KotlinSyntheticClass.Kind.PACKAGE_PART) {
|
||||||
assert(sourceFiles.size == 1) { "Package part from several source files: $sourceFiles" }
|
assert(sourceFiles.size == 1) { "Package part from several source files: $sourceFiles" }
|
||||||
|
|
||||||
packagePartMap.putPackagePartSourceData(sourceFiles.first(), className)
|
packagePartMap.putPackagePartSourceData(sourceFiles.first(), className)
|
||||||
val inlinesChanged = inlineFunctionsMap.process(className, fileBytes)
|
val inlinesChanged = inlineFunctionsMap.process(className, fileBytes)
|
||||||
val constantsChanged = constantsMap.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
|
return DO_NOTHING
|
||||||
@@ -497,8 +509,9 @@ public class IncrementalCacheImpl(targetDataRoot: File): StorageOwner, Increment
|
|||||||
|
|
||||||
enum class RecompilationDecision {
|
enum class RecompilationDecision {
|
||||||
DO_NOTHING
|
DO_NOTHING
|
||||||
COMPILE_OTHERS
|
RECOMPILE_OTHERS_IN_CHUNK
|
||||||
RECOMPILE_ALL
|
RECOMPILE_OTHERS_WITH_DEPENDANTS
|
||||||
|
RECOMPILE_ALL_CHUNK_AND_DEPENDANTS
|
||||||
|
|
||||||
fun merge(other: RecompilationDecision): RecompilationDecision {
|
fun merge(other: RecompilationDecision): RecompilationDecision {
|
||||||
return if (other.ordinal() > this.ordinal()) other else this
|
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