@@ -24,8 +24,6 @@ import gnu.trove.THashSet
|
|||||||
import org.jetbrains.jps.ModuleChunk
|
import org.jetbrains.jps.ModuleChunk
|
||||||
import org.jetbrains.jps.builders.BuildTarget
|
import org.jetbrains.jps.builders.BuildTarget
|
||||||
import org.jetbrains.jps.builders.DirtyFilesHolder
|
import org.jetbrains.jps.builders.DirtyFilesHolder
|
||||||
import org.jetbrains.jps.builders.impl.BuildTargetRegistryImpl
|
|
||||||
import org.jetbrains.jps.builders.impl.TargetOutputIndexImpl
|
|
||||||
import org.jetbrains.jps.builders.java.JavaBuilderUtil
|
import org.jetbrains.jps.builders.java.JavaBuilderUtil
|
||||||
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor
|
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor
|
||||||
import org.jetbrains.jps.incremental.*
|
import org.jetbrains.jps.incremental.*
|
||||||
@@ -59,6 +57,7 @@ import org.jetbrains.kotlin.load.kotlin.ModuleMapping
|
|||||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCache
|
||||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||||
import org.jetbrains.kotlin.modules.TargetId
|
import org.jetbrains.kotlin.modules.TargetId
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.progress.CompilationCanceledException
|
import org.jetbrains.kotlin.progress.CompilationCanceledException
|
||||||
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
||||||
import org.jetbrains.kotlin.utils.LibraryUtils
|
import org.jetbrains.kotlin.utils.LibraryUtils
|
||||||
@@ -687,12 +686,12 @@ private fun processChanges(
|
|||||||
compiledFiles: Set<File>,
|
compiledFiles: Set<File>,
|
||||||
allCompiledFiles: MutableSet<File>,
|
allCompiledFiles: MutableSet<File>,
|
||||||
dataManager: BuildDataManager,
|
dataManager: BuildDataManager,
|
||||||
caches: List<IncrementalCacheImpl>,
|
caches: Collection<IncrementalCacheImpl>,
|
||||||
compilationResult: CompilationResult,
|
compilationResult: CompilationResult,
|
||||||
fsOperations: FSOperationsHelper
|
fsOperations: FSOperationsHelper
|
||||||
) {
|
) {
|
||||||
if (IncrementalCompilation.isExperimental()) {
|
if (IncrementalCompilation.isExperimental()) {
|
||||||
compilationResult.doProcessChangesUsingLookups(compiledFiles, dataManager, fsOperations)
|
doProcessChangesUsingLookups(compilationResult.changes.asIterable(), compiledFiles, dataManager, fsOperations, caches)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
compilationResult.doProcessChanges(compiledFiles, allCompiledFiles, caches, fsOperations)
|
compilationResult.doProcessChanges(compiledFiles, allCompiledFiles, caches, fsOperations)
|
||||||
@@ -728,33 +727,72 @@ private fun CompilationResult.doProcessChanges(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun CompilationResult.doProcessChangesUsingLookups(
|
private fun doProcessChangesUsingLookups(
|
||||||
|
changes: Iterable<ChangeInfo>,
|
||||||
compiledFiles: Set<File>,
|
compiledFiles: Set<File>,
|
||||||
dataManager: BuildDataManager,
|
dataManager: BuildDataManager,
|
||||||
fsOperations: FSOperationsHelper
|
fsOperations: FSOperationsHelper,
|
||||||
|
caches: Collection<IncrementalCacheImpl>
|
||||||
) {
|
) {
|
||||||
|
val dirtyLookupSymbols = HashSet<LookupSymbol>()
|
||||||
val lookupStorage = dataManager.getStorage(KotlinDataContainerTarget, LookupStorageProvider)
|
val lookupStorage = dataManager.getStorage(KotlinDataContainerTarget, LookupStorageProvider)
|
||||||
|
|
||||||
KotlinBuilder.LOG.debug("Start processing changes")
|
KotlinBuilder.LOG.debug("Start processing changes")
|
||||||
|
|
||||||
// TODO group by fqName?
|
val changedSignatureFqNames = changes.filterIsInstance<ChangeInfo.SignatureChanged>().map { it.fqName }
|
||||||
for (change in changes) {
|
for (classFqName in getSubtypesOf(changedSignatureFqNames, caches)) {
|
||||||
KotlinBuilder.LOG.debug("Process $change")
|
val scope = classFqName.parent().asString()
|
||||||
|
val name = classFqName.shortName().identifier
|
||||||
if (change !is ChangeInfo.MembersChanged) continue
|
dirtyLookupSymbols.add(LookupSymbol(name, scope))
|
||||||
|
|
||||||
val files = change.names.asSequence()
|
|
||||||
.flatMap { lookupStorage.get(LookupSymbol(it, change.fqName.asString())).asSequence() }
|
|
||||||
.map(::File)
|
|
||||||
|
|
||||||
fsOperations.markFiles(files.asIterable(), excludeFiles = compiledFiles)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (change in changes.filterIsInstance<ChangeInfo.MembersChanged>()) {
|
||||||
|
val scopes = getSubtypesOf(listOf(change.fqName), caches).map { it.asString() }
|
||||||
|
|
||||||
|
for (name in change.names) {
|
||||||
|
for (scope in scopes) {
|
||||||
|
dirtyLookupSymbols.add(LookupSymbol(name, scope))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val dirtyFiles = HashSet<File>()
|
||||||
|
|
||||||
|
for (lookup in dirtyLookupSymbols) {
|
||||||
|
val affectedFiles = lookupStorage.get(lookup).map(::File)
|
||||||
|
|
||||||
|
KotlinBuilder.LOG.debug { "${lookup.scope}#${lookup.name} caused recompilation of: $affectedFiles" }
|
||||||
|
|
||||||
|
dirtyFiles.addAll(affectedFiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
fsOperations.markFiles(dirtyFiles.asIterable(), excludeFiles = compiledFiles)
|
||||||
KotlinBuilder.LOG.debug("End of processing changes")
|
KotlinBuilder.LOG.debug("End of processing changes")
|
||||||
}
|
}
|
||||||
|
|
||||||
private val Iterable<BuildTarget<*>>.moduleTargets: Iterable<ModuleBuildTarget>
|
/**
|
||||||
get() = filterIsInstance(ModuleBuildTarget::class.java)
|
* Gets subtypes of given types inclusively
|
||||||
|
*/
|
||||||
|
private fun getSubtypesOf(
|
||||||
|
typeFqNames: Iterable<FqName>,
|
||||||
|
caches: Collection<IncrementalCacheImpl>
|
||||||
|
): Set<FqName> {
|
||||||
|
val types = typeFqNames.toCollection(LinkedList())
|
||||||
|
val subtypes = hashSetOf<FqName>()
|
||||||
|
|
||||||
|
while (types.isNotEmpty()) {
|
||||||
|
val unprocessedType = types.pollFirst()
|
||||||
|
|
||||||
|
caches.asSequence()
|
||||||
|
.flatMap { it.getSubtypesOf(unprocessedType) }
|
||||||
|
.filter { it !in subtypes }
|
||||||
|
.forEach { types.addLast(it) }
|
||||||
|
|
||||||
|
subtypes.add(unprocessedType)
|
||||||
|
}
|
||||||
|
|
||||||
|
return subtypes
|
||||||
|
}
|
||||||
|
|
||||||
private fun getLookupTracker(project: JpsProject): LookupTracker {
|
private fun getLookupTracker(project: JpsProject): LookupTracker {
|
||||||
var lookupTracker = LookupTracker.DO_NOTHING
|
var lookupTracker = LookupTracker.DO_NOTHING
|
||||||
@@ -855,3 +893,9 @@ class GeneratedJvmClass (
|
|||||||
"Couldn't load KotlinClass from $outputFile; it may happen because class doesn't have valid Kotlin annotations"
|
"Couldn't load KotlinClass from $outputFile; it may happen because class doesn't have valid Kotlin annotations"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inline fun Logger.debug(message: ()->String) {
|
||||||
|
if (isDebugEnabled) {
|
||||||
|
debug(message())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -105,8 +105,8 @@ class IncrementalCacheImpl(
|
|||||||
private val dependents = arrayListOf<IncrementalCacheImpl>()
|
private val dependents = arrayListOf<IncrementalCacheImpl>()
|
||||||
private val outputDir = requireNotNull(target.outputDir) { "Target is expected to have output directory: $target" }
|
private val outputDir = requireNotNull(target.outputDir) { "Target is expected to have output directory: $target" }
|
||||||
|
|
||||||
private val dependentsWithThis: Iterable<IncrementalCacheImpl>
|
private val dependentsWithThis: Sequence<IncrementalCacheImpl>
|
||||||
get() = dependents + this
|
get() = sequenceOf(this).plus(dependents.asSequence())
|
||||||
|
|
||||||
override fun registerInline(fromPath: String, jvmSignature: String, toPath: String) {
|
override fun registerInline(fromPath: String, jvmSignature: String, toPath: String) {
|
||||||
inlinedTo.add(fromPath, jvmSignature, toPath)
|
inlinedTo.add(fromPath, jvmSignature, toPath)
|
||||||
@@ -142,6 +142,9 @@ class IncrementalCacheImpl(
|
|||||||
return result.map { File(it) }
|
return result.map { File(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getSubtypesOf(className: FqName): Sequence<FqName> =
|
||||||
|
dependentsWithThis.flatMap { it.subtypesMap[className].asSequence() }
|
||||||
|
|
||||||
fun cleanDirtyInlineFunctions() {
|
fun cleanDirtyInlineFunctions() {
|
||||||
dirtyInlineFunctionsMap.clean()
|
dirtyInlineFunctionsMap.clean()
|
||||||
}
|
}
|
||||||
@@ -600,9 +603,14 @@ class IncrementalCacheImpl(
|
|||||||
val supertypes = classData.classProto.supertypes(TypeTable(classData.classProto.typeTable))
|
val supertypes = classData.classProto.supertypes(TypeTable(classData.classProto.typeTable))
|
||||||
val parents = supertypes.map { classData.nameResolver.getClassId(it.className).asSingleFqName() }
|
val parents = supertypes.map { classData.nameResolver.getClassId(it.className).asSingleFqName() }
|
||||||
.filter { it.asString() != "kotlin.Any" }
|
.filter { it.asString() != "kotlin.Any" }
|
||||||
|
.toSet()
|
||||||
val child = kotlinClass.classId.asSingleFqName()
|
val child = kotlinClass.classId.asSingleFqName()
|
||||||
|
|
||||||
parents.forEach { subtypesMap.add(it, child) }
|
parents.forEach { subtypesMap.add(it, child) }
|
||||||
|
|
||||||
|
val removedSupertypes = supertypesMap[child].filter { it !in parents }
|
||||||
|
removedSupertypes.forEach { subtypesMap.removeValues(it, setOf(child)) }
|
||||||
|
|
||||||
supertypesMap[child] = parents
|
supertypesMap[child] = parents
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user