diff --git a/build-common/src/org/jetbrains/kotlin/build/generatedFiles.kt b/build-common/src/org/jetbrains/kotlin/build/generatedFiles.kt index e93777d96d1..cb211ee569c 100644 --- a/build-common/src/org/jetbrains/kotlin/build/generatedFiles.kt +++ b/build-common/src/org/jetbrains/kotlin/build/generatedFiles.kt @@ -21,17 +21,15 @@ import org.jetbrains.kotlin.load.kotlin.ModuleMapping import org.jetbrains.kotlin.utils.sure import java.io.File -open class GeneratedFile( - val target: Target, - val sourceFiles: Collection, - val outputFile: File +open class GeneratedFile( + val sourceFiles: Collection, + val outputFile: File ) -class GeneratedJvmClass ( - target: Target, +class GeneratedJvmClass ( sourceFiles: Collection, outputFile: File -) : GeneratedFile(target, sourceFiles, outputFile) { +) : GeneratedFile(sourceFiles, outputFile) { val outputClass = LocalFileKotlinClass.create(outputFile).sure { "Couldn't load KotlinClass from $outputFile; it may happen because class doesn't have valid Kotlin annotations" } diff --git a/build-common/src/org/jetbrains/kotlin/compilerRunner/SimpleOutputItem.kt b/build-common/src/org/jetbrains/kotlin/compilerRunner/SimpleOutputItem.kt index 75684157a39..55102f2b56d 100644 --- a/build-common/src/org/jetbrains/kotlin/compilerRunner/SimpleOutputItem.kt +++ b/build-common/src/org/jetbrains/kotlin/compilerRunner/SimpleOutputItem.kt @@ -16,9 +16,17 @@ package org.jetbrains.kotlin.compilerRunner +import org.jetbrains.kotlin.build.GeneratedFile +import org.jetbrains.kotlin.build.GeneratedJvmClass import java.io.File data class SimpleOutputItem(val sourceFiles: Collection, val outputFile: File) { override fun toString(): String = "$sourceFiles->$outputFile" } + +fun SimpleOutputItem.toGeneratedFile(): GeneratedFile = + when { + outputFile.name.endsWith(".class") -> GeneratedJvmClass(sourceFiles, outputFile) + else -> GeneratedFile(sourceFiles, outputFile) + } \ No newline at end of file diff --git a/build-common/src/org/jetbrains/kotlin/incremental/IncrementalCacheImpl.kt b/build-common/src/org/jetbrains/kotlin/incremental/IncrementalCacheImpl.kt index 39d68cd749a..6d9bec082b0 100644 --- a/build-common/src/org/jetbrains/kotlin/incremental/IncrementalCacheImpl.kt +++ b/build-common/src/org/jetbrains/kotlin/incremental/IncrementalCacheImpl.kt @@ -114,7 +114,7 @@ open class IncrementalCacheImpl( return CompilationResult.NO_CHANGES } - open fun saveFileToCache(generatedClass: GeneratedJvmClass<*>): CompilationResult { + open fun saveFileToCache(generatedClass: GeneratedJvmClass): CompilationResult { val sourceFiles: Collection = generatedClass.sourceFiles val kotlinClass: LocalFileKotlinClass = generatedClass.outputClass val className = kotlinClass.className diff --git a/build-common/src/org/jetbrains/kotlin/incremental/buildUtil.kt b/build-common/src/org/jetbrains/kotlin/incremental/buildUtil.kt index 9f8bfe6f099..948e39f187b 100644 --- a/build-common/src/org/jetbrains/kotlin/incremental/buildUtil.kt +++ b/build-common/src/org/jetbrains/kotlin/incremental/buildUtil.kt @@ -77,13 +77,13 @@ fun makeCompileServices( } fun updateIncrementalCache( - generatedFiles: List>, + generatedFiles: Iterable, cache: IncrementalCacheImpl ): CompilationResult { var changesInfo = CompilationResult.NO_CHANGES for (generatedFile in generatedFiles) { when { - generatedFile is GeneratedJvmClass<*> -> changesInfo += cache.saveFileToCache(generatedFile) + generatedFile is GeneratedJvmClass -> changesInfo += cache.saveFileToCache(generatedFile) generatedFile.outputFile.isModuleMappingFile() -> changesInfo += cache.saveModuleMappingToCache(generatedFile.sourceFiles, generatedFile.outputFile) } } diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt index 6d368a7eb4e..86caa65513c 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt @@ -29,9 +29,7 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler -import org.jetbrains.kotlin.compilerRunner.ArgumentUtils -import org.jetbrains.kotlin.compilerRunner.OutputItemsCollector -import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl +import org.jetbrains.kotlin.compilerRunner.* import org.jetbrains.kotlin.config.IncrementalCompilation import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.multiproject.ArtifactChangesProvider @@ -180,16 +178,16 @@ abstract class IncrementalCompilerRunner< protected open fun markOutputDirty(caches: CacheManager, dirtySources: List) { } - protected abstract fun compareAndUpdateCache(caches: CacheManager, generatedFiles: List>): CompilationResult + protected abstract fun compareAndUpdateCache(caches: CacheManager, generatedFiles: List): CompilationResult protected open fun preBuildHook(args: Args, compilationMode: CompilationMode) {} protected open fun postCompilationHook(exitCode: ExitCode) {} - protected open fun additionalDirtyFiles(caches: CacheManager, generatedFiles: List>): Iterable = + protected open fun additionalDirtyFiles(caches: CacheManager, generatedFiles: List): Iterable = emptyList() protected abstract fun compileIncrementally(args: Args, caches: CacheManager, allKotlinSources: List, compilationMode: CompilationMode, messageCollector: MessageCollector): ExitCode - protected data class CompileChangedResults(val exitCode: ExitCode, val generatedFiles: List>) + protected data class CompileChangedResults(val exitCode: ExitCode, val generatedFiles: List) protected sealed class CompilationMode { class Incremental(val dirtyFiles: Set) : CompilationMode() @@ -334,7 +332,7 @@ class IncrementalJvmCompilerRunner( } } - override fun compareAndUpdateCache(caches: IncrementalJvmCachesManager, generatedFiles: List>): CompilationResult = + override fun compareAndUpdateCache(caches: IncrementalJvmCachesManager, generatedFiles: List): CompilationResult = updateIncrementalCache(generatedFiles, caches.platformCache) override fun compileIncrementally( @@ -358,7 +356,7 @@ class IncrementalJvmCompilerRunner( val allSourcesToCompile = HashSet() var exitCode = ExitCode.OK - val allGeneratedFiles = hashSetOf>() + val allGeneratedFiles = hashSetOf() while (dirtySources.any()) { markOutputDirty(caches, dirtySources) @@ -436,7 +434,7 @@ class IncrementalJvmCompilerRunner( override fun additionalDirtyFiles( caches: IncrementalJvmCachesManager, - generatedFiles: List> + generatedFiles: List ): Iterable { val cache = caches.platformCache val result = HashSet() @@ -447,7 +445,7 @@ class IncrementalJvmCompilerRunner( } for (generatedFile in generatedFiles) { - if (generatedFile !is GeneratedJvmClass<*>) continue + if (generatedFile !is GeneratedJvmClass) continue val outputClass = generatedFile.outputClass @@ -511,14 +509,7 @@ class IncrementalJvmCompilerRunner( reporter.report { "compiling with classpath: ${classpath.toList().sorted().joinToString()}" } val compileServices = makeCompileServices(incrementalCaches, lookupTracker, compilationCanceledStatus) val exitCode = compiler.exec(messageCollector, compileServices, args) - val generatedFiles = outputItemCollector.outputs.map { - val outputItem = it.outputFile - val sourceFiles = it.sourceFiles - when (outputItem.extension) { - "class" -> GeneratedJvmClass(targetId, sourceFiles, outputItem) - else -> GeneratedFile(targetId, sourceFiles, outputItem) - } - } + val generatedFiles = outputItemCollector.outputs.map(SimpleOutputItem::toGeneratedFile) reporter.reportCompileIteration(sourcesToCompile, exitCode) return CompileChangedResults(exitCode, generatedFiles) } diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/InputsCache.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/InputsCache.kt index 801ce1f8c16..d02c25fba6c 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/InputsCache.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/InputsCache.kt @@ -40,7 +40,7 @@ class InputsCache( // generatedFiles can contain multiple entries with the same source file // for example Kapt3 IC will generate a .java stub and .class stub for each source file - fun registerOutputForSourceFiles(generatedFiles: List>) { + fun registerOutputForSourceFiles(generatedFiles: List) { val sourceToOutput = MultiMap() for (generatedFile in generatedFiles) { diff --git a/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt b/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt index a0d9523dc55..da1f8c92fa8 100644 --- a/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt +++ b/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt @@ -22,7 +22,6 @@ import com.intellij.openapi.util.io.FileUtil import com.intellij.util.containers.ContainerUtil import com.intellij.util.containers.MultiMap import gnu.trove.THashSet -import jdk.nashorn.internal.lookup.Lookup import org.jetbrains.jps.ModuleChunk import org.jetbrains.jps.builders.BuildTarget import org.jetbrains.jps.builders.DirtyFilesHolder @@ -41,17 +40,13 @@ import org.jetbrains.jps.model.module.JpsModule import org.jetbrains.kotlin.build.GeneratedFile import org.jetbrains.kotlin.build.GeneratedJvmClass import org.jetbrains.kotlin.build.JvmBuildMetaInfo -import org.jetbrains.kotlin.build.isModuleMappingFile import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.* import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil -import org.jetbrains.kotlin.compilerRunner.JpsCompilerEnvironment -import org.jetbrains.kotlin.compilerRunner.JpsKotlinCompilerRunner -import org.jetbrains.kotlin.compilerRunner.OutputItemsCollector -import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl +import org.jetbrains.kotlin.compilerRunner.* import org.jetbrains.kotlin.config.CompilerRunnerConstants import org.jetbrains.kotlin.config.CompilerRunnerConstants.INTERNAL_ERROR_PREFIX import org.jetbrains.kotlin.config.IncrementalCompilation @@ -311,9 +306,7 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) { return OK } - @Suppress("REIFIED_TYPE_UNSAFE_SUBSTITUTION") - val generatedClasses = generatedFiles.filterIsInstance>() - updateJavaMappings(chunk, compilationErrors, context, dirtyFilesHolder, filesToCompile, generatedClasses, incrementalCaches) + updateJavaMappings(chunk, context, dirtyFilesHolder, filesToCompile, generatedFiles, incrementalCaches) if (!IncrementalCompilation.isEnabled()) { return OK @@ -321,7 +314,9 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) { context.checkCanceled() - val changesInfo = updateKotlinIncrementalCache(compilationErrors, incrementalCaches, generatedFiles) + val changesInfo = generatedFiles.entries.fold(CompilationResult.NO_CHANGES) { acc, (target, files) -> + acc + updateIncrementalCache(files, incrementalCaches[target]!!) + } updateLookupStorage(chunk, lookupTracker, dataManager, dirtyFilesHolder, filesToCompile) if (isChunkRebuilding) { @@ -517,7 +512,7 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) { private fun getGeneratedFiles( chunk: ModuleChunk, outputItemCollector: OutputItemsCollectorImpl - ): List> { + ): Map> { // If there's only one target, this map is empty: get() always returns null, and the representativeTarget will be used below val sourceToTarget = HashMap() if (chunk.targets.size > 1) { @@ -528,34 +523,21 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) { } } - val result = ArrayList>() - val representativeTarget = chunk.representativeTarget() - for (outputItem in outputItemCollector.outputs) { - val sourceFiles = outputItem.sourceFiles - val outputFile = outputItem.outputFile - val target = - sourceFiles.firstOrNull()?.let { sourceToTarget[it] } ?: - chunk.targets.singleOrNull { it.outputDir?.let { outputFile.startsWith(it) } ?: false } ?: - representativeTarget + fun SimpleOutputItem.target() = + sourceFiles.firstOrNull()?.let { sourceToTarget[it] } ?: + chunk.targets.singleOrNull { it.outputDir?.let { outputFile.startsWith(it) } ?: false } ?: + representativeTarget - if (outputFile.name.endsWith(".class")) { - result.add(GeneratedJvmClass(target, sourceFiles, outputFile)) - } - else { - result.add(GeneratedFile(target, sourceFiles, outputFile)) - } - } - return result + return outputItemCollector.outputs.groupBy(SimpleOutputItem::target, SimpleOutputItem::toGeneratedFile) } private fun updateJavaMappings( chunk: ModuleChunk, - compilationErrors: Boolean, context: CompileContext, dirtyFilesHolder: DirtyFilesHolder, filesToCompile: MultiMap, - generatedClasses: List>, + outputItems: Map>, incrementalCaches: Map ) { val previousMappings = context.projectDescriptor.dataManager.mappings @@ -568,8 +550,8 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) { files } - fun getOldSourceFiles(generatedClass: GeneratedJvmClass): Set { - val cache = incrementalCaches[generatedClass.target] ?: return emptySet() + fun getOldSourceFiles(target: ModuleBuildTarget, generatedClass: GeneratedJvmClass): Set { + val cache = incrementalCaches[target] ?: return emptySet() val className = generatedClass.outputClass.className if (!cache.isMultifileFacade(className)) return emptySet() @@ -578,65 +560,34 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) { return previousMappings.getClassSources(name)?.toSet() ?: emptySet() } - for (generatedClass in generatedClasses) { - val sourceFiles = THashSet(FileUtil.FILE_HASHING_STRATEGY) - sourceFiles.addAll(getOldSourceFiles(generatedClass)) - sourceFiles.removeAll(targetDirtyFiles[generatedClass.target] ?: emptySet()) - sourceFiles.addAll(generatedClass.sourceFiles) + for ((target, outputs) in outputItems) { + for (output in outputs) { + if (output !is GeneratedJvmClass) continue - callback.associate( - FileUtil.toSystemIndependentName(generatedClass.outputFile.canonicalPath), - sourceFiles.map { FileUtil.toSystemIndependentName(it.canonicalPath) }, - ClassReader(generatedClass.outputClass.fileContents) - ) - } + val sourceFiles = THashSet(FileUtil.FILE_HASHING_STRATEGY) + sourceFiles.addAll(getOldSourceFiles(target, output)) + sourceFiles.removeAll(targetDirtyFiles[target] ?: emptySet()) + sourceFiles.addAll(output.sourceFiles) - val allCompiled = filesToCompile.values() - val successfullyCompiled = if (compilationErrors) listOf() else allCompiled - - JavaBuilderUtil.registerFilesToCompile(context, allCompiled) - JavaBuilderUtil.registerSuccessfullyCompiled(context, successfullyCompiled) - } - - private fun registerOutputItems(outputConsumer: ModuleLevelBuilder.OutputConsumer, generatedFiles: List>) { - for (generatedFile in generatedFiles) { - outputConsumer.registerOutputFile(generatedFile.target, generatedFile.outputFile, generatedFile.sourceFiles.map { it.path }) - } - } - - private fun updateKotlinIncrementalCache( - compilationErrors: Boolean, - incrementalCaches: Map, - generatedFiles: List> - ): CompilationResult { - - assert(IncrementalCompilation.isEnabled()) { "updateKotlinIncrementalCache should not be called when incremental compilation disabled" } - - var changesInfo = CompilationResult.NO_CHANGES - for (generatedFile in generatedFiles) { - val ic = incrementalCaches[generatedFile.target]!! - val newChangesInfo = - if (generatedFile is GeneratedJvmClass) { - ic.saveFileToCache(generatedFile) - } - else if (generatedFile.outputFile.isModuleMappingFile()) { - ic.saveModuleMappingToCache(generatedFile.sourceFiles, generatedFile.outputFile) - } - else { - continue - } - - changesInfo += newChangesInfo - } - - if (!compilationErrors) { - incrementalCaches.values.forEach { - val newChangesInfo = it.clearCacheForRemovedClasses() - changesInfo += newChangesInfo + callback.associate( + FileUtil.toSystemIndependentName(output.outputFile.canonicalPath), + sourceFiles.map { FileUtil.toSystemIndependentName(it.canonicalPath) }, + ClassReader(output.outputClass.fileContents) + ) } } - return changesInfo + val allCompiled = filesToCompile.values() + JavaBuilderUtil.registerFilesToCompile(context, allCompiled) + JavaBuilderUtil.registerSuccessfullyCompiled(context, allCompiled) + } + + private fun registerOutputItems(outputConsumer: OutputConsumer, outputItems: Map>) { + for ((target, outputs) in outputItems) { + for (output in outputs) { + outputConsumer.registerOutputFile(target, output.outputFile, output.sourceFiles.map { it.path }) + } + } } private fun updateLookupStorage(