IncrementalCacheImpl: do not recompile other files if all changes are private
Original commit: b3659486d9
This commit is contained in:
@@ -25,6 +25,7 @@ import org.jetbrains.jps.incremental.storage.BuildDataManager
|
||||
import org.jetbrains.jps.incremental.storage.PathStringDescriptor
|
||||
import org.jetbrains.jps.incremental.storage.StorageOwner
|
||||
import org.jetbrains.kotlin.config.IncrementalCompilation
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.jps.build.KotlinBuilder
|
||||
import org.jetbrains.kotlin.jps.incremental.IncrementalCacheImpl.RecompilationDecision.DO_NOTHING
|
||||
import org.jetbrains.kotlin.jps.incremental.IncrementalCacheImpl.RecompilationDecision.RECOMPILE_ALL_IN_CHUNK_AND_DEPENDANTS
|
||||
@@ -38,7 +39,11 @@ import org.jetbrains.kotlin.load.kotlin.header.isCompatiblePackageFacadeKind
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.serialization.Flags
|
||||
import org.jetbrains.kotlin.serialization.ProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.jvm.BitEncoding
|
||||
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil
|
||||
import org.jetbrains.kotlin.serialization.deserialization.visibility
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
import org.jetbrains.org.objectweb.asm.*
|
||||
import java.io.*
|
||||
@@ -150,14 +155,14 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen
|
||||
val decision = when {
|
||||
header.isCompatiblePackageFacadeKind() ->
|
||||
getRecompilationDecision(
|
||||
protoChanged = protoMap.put(className, BitEncoding.decodeBytes(header.annotationData!!)),
|
||||
protoChanged = protoMap.put(className, BitEncoding.decodeBytes(header.annotationData!!), isPackage = true),
|
||||
constantsChanged = false,
|
||||
inlinesChanged = false
|
||||
)
|
||||
header.isCompatibleClassKind() ->
|
||||
when (header.classKind!!) {
|
||||
JvmAnnotationNames.KotlinClass.Kind.CLASS -> getRecompilationDecision(
|
||||
protoChanged = protoMap.put(className, BitEncoding.decodeBytes(header.annotationData!!)),
|
||||
protoChanged = protoMap.put(className, BitEncoding.decodeBytes(header.annotationData!!), isPackage = false),
|
||||
constantsChanged = constantsMap.process(className, fileBytes),
|
||||
inlinesChanged = inlineFunctionsMap.process(className, fileBytes)
|
||||
)
|
||||
@@ -299,13 +304,18 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen
|
||||
ByteArrayExternalizer
|
||||
)
|
||||
|
||||
public fun put(className: JvmClassName, data: ByteArray): Boolean {
|
||||
public fun put(className: JvmClassName, data: ByteArray, isPackage: Boolean): Boolean {
|
||||
val key = className.getInternalName()
|
||||
val oldData = storage[key]
|
||||
if (Arrays.equals(data, oldData)) {
|
||||
return false
|
||||
}
|
||||
storage.put(key, data)
|
||||
|
||||
if (oldData != null && isOpenPartNotChanged(oldData, data, isPackage)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -320,6 +330,53 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen
|
||||
override fun dumpValue(value: ByteArray): String {
|
||||
return java.lang.Long.toHexString(value.md5())
|
||||
}
|
||||
|
||||
private fun isOpenPartNotChanged(oldData: ByteArray, newData: ByteArray, isPackageFacade: Boolean): Boolean {
|
||||
if (isPackageFacade) {
|
||||
return isPackageFacadeOpenPartNotChanged(oldData, newData)
|
||||
}
|
||||
else {
|
||||
return isClassOpenPartNotChanged(oldData, newData)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isPackageFacadeOpenPartNotChanged(oldData: ByteArray, newData: ByteArray): Boolean {
|
||||
val oldPackageData = JvmProtoBufUtil.readPackageDataFrom(oldData)
|
||||
val newPackageData = JvmProtoBufUtil.readPackageDataFrom(newData)
|
||||
|
||||
val compareObject = ProtoCompareGenerated(oldPackageData.nameResolver, newPackageData.nameResolver)
|
||||
return compareObject.checkEquals(oldPackageData.packageProto, newPackageData.packageProto)
|
||||
}
|
||||
|
||||
private fun isClassOpenPartNotChanged(oldData: ByteArray, newData: ByteArray): Boolean {
|
||||
val oldClassData = JvmProtoBufUtil.readClassDataFrom(oldData)
|
||||
val newClassData = JvmProtoBufUtil.readClassDataFrom(newData)
|
||||
|
||||
val compareObject = object : ProtoCompareGenerated(oldClassData.nameResolver, newClassData.nameResolver) {
|
||||
override fun checkEqualsClassMember(old: ProtoBuf.Class, new: ProtoBuf.Class): Boolean =
|
||||
checkEquals(old.memberList, new.memberList)
|
||||
|
||||
override fun checkEqualsClassSecondaryConstructor(old: ProtoBuf.Class, new: ProtoBuf.Class): Boolean =
|
||||
checkEquals(old.secondaryConstructorList, new.secondaryConstructorList)
|
||||
|
||||
private fun checkEquals(oldList: List<ProtoBuf.Callable>, newList: List<ProtoBuf.Callable>): Boolean {
|
||||
val oldListFiltered = oldList.filter { !it.isPrivate() }
|
||||
val newListFiltered = newList.filter { !it.isPrivate() }
|
||||
|
||||
if (oldListFiltered.size() != newListFiltered.size()) return false
|
||||
|
||||
for (i in oldListFiltered.indices) {
|
||||
if (!checkEquals(oldListFiltered[i], newListFiltered[i])) return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun ProtoBuf.Callable.isPrivate(): Boolean = Visibilities.isPrivate(visibility(Flags.VISIBILITY.get(flags)))
|
||||
}
|
||||
|
||||
return compareObject.checkEquals(oldClassData.classProto, newClassData.classProto)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class ConstantsMap : BasicMap<Map<String, Any>>() {
|
||||
|
||||
Reference in New Issue
Block a user