JPS: Fix JvmMultifileClass processing for IR backend

#KT-44644 Fixed

(cherry picked from commit aa683d3b2a)

Original commit: ef3c73554fc64d9837019ed9cf9e512bbd2b20f3
This commit is contained in:
Aleksei.Cherepanov
2021-02-01 13:08:43 +03:00
parent 8a0eda2ca9
commit 8b38a752d8
12 changed files with 123 additions and 24 deletions
@@ -29,6 +29,7 @@ import org.jetbrains.jps.incremental.ModuleLevelBuilder.ExitCode.*
import org.jetbrains.jps.incremental.java.JavaBuilder
import org.jetbrains.jps.model.JpsProject
import org.jetbrains.kotlin.build.GeneratedFile
import org.jetbrains.kotlin.build.GeneratedJvmClass
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
@@ -48,6 +49,7 @@ import org.jetbrains.kotlin.jps.incremental.JpsLookupStorageManager
import org.jetbrains.kotlin.jps.model.kotlinKind
import org.jetbrains.kotlin.jps.targets.KotlinJvmModuleBuildTarget
import org.jetbrains.kotlin.jps.targets.KotlinModuleBuildTarget
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.preloading.ClassCondition
import org.jetbrains.kotlin.utils.KotlinPaths
@@ -439,6 +441,9 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
}
val generatedFiles = getGeneratedFiles(context, chunk, environment.outputItemsCollector)
markDirtyComplementaryMultifileClasses(generatedFiles, kotlinContext, incrementalCaches, fsOperations)
val kotlinTargets = kotlinContext.targetsBinding
for ((target, outputItems) in generatedFiles) {
val kotlinTarget = kotlinTargets[target] ?: error("Could not find Kotlin target for JPS target $target")
@@ -526,14 +531,23 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
for (target in kotlinChunk.targets) {
val cache = incrementalCaches[target]
val jpsTarget = target.jpsModuleBuildTarget
val targetDirtyFiles = dirtyFilesHolder.byTarget[jpsTarget]
if (cache != null && targetDirtyFiles != null) {
val complementaryFiles = cache.getComplementaryFilesRecursive(
targetDirtyFiles.dirty.keys + targetDirtyFiles.removed
)
val dirtyFiles = targetDirtyFiles.dirty.keys + targetDirtyFiles.removed
val complementaryFiles = cache.getComplementaryFilesRecursive(dirtyFiles)
fsOperations.markFilesForCurrentRound(jpsTarget, complementaryFiles)
// Get all parts of @JvmMultifileClass file for simultaneous rebuild
var dirtyMultifileClassFiles: Collection<File> = emptyList()
if (cache is IncrementalJvmCache) {
dirtyMultifileClassFiles = cache.classesBySources(dirtyFiles)
.filter { cache.isMultifileFacade(it) }
.flatMap { cache.getAllPartsOfMultifileFacade(it).orEmpty() }
.flatMap { cache.sourcesByInternalName(it) }
.distinct()
.filter { !dirtyFiles.contains(it) }
}
fsOperations.markFilesForCurrentRound(jpsTarget, complementaryFiles + dirtyMultifileClassFiles)
cache.markDirty(targetDirtyFiles.dirty.keys + targetDirtyFiles.removed)
}
@@ -666,6 +680,28 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
lookupStorage.addAll(lookupTracker.lookups, lookupTracker.pathInterner.values)
}
}
private fun markDirtyComplementaryMultifileClasses(
generatedFiles: Map<ModuleBuildTarget, List<GeneratedFile>>,
kotlinContext: KotlinCompileContext,
incrementalCaches: Map<KotlinModuleBuildTarget<*>, JpsIncrementalCache>,
fsOperations: FSOperationsHelper
) {
for ((target, files) in generatedFiles) {
val kotlinModuleBuilderTarget = kotlinContext.targetsBinding[target] ?: continue
val cache = incrementalCaches[kotlinModuleBuilderTarget] as? IncrementalJvmCache ?: continue
val generated = files.filterIsInstance<GeneratedJvmClass>()
val multifileClasses = generated.filter { it.outputClass.classHeader.kind == KotlinClassHeader.Kind.MULTIFILE_CLASS }
val expectedAllParts = multifileClasses.flatMap { cache.getAllPartsOfMultifileFacade(it.outputClass.className).orEmpty() }
if (multifileClasses.isEmpty()) continue
val actualParts = generated.filter { it.outputClass.classHeader.kind == KotlinClassHeader.Kind.MULTIFILE_CLASS_PART }
.map { it.outputClass.className.toString() }
if (!actualParts.containsAll(expectedAllParts)) {
fsOperations.markFiles(expectedAllParts.flatMap { cache.sourcesByInternalName(it) }
+ multifileClasses.flatMap { it.sourceFiles })
}
}
}
}
private class JpsICReporter : ICReporterBase() {