Remove Target parameter from GeneratedFile

This commit is contained in:
Alexey Tsvetkov
2017-07-03 17:46:51 +03:00
parent af73082fcc
commit 9727ec401b
7 changed files with 63 additions and 115 deletions
@@ -21,17 +21,15 @@ import org.jetbrains.kotlin.load.kotlin.ModuleMapping
import org.jetbrains.kotlin.utils.sure import org.jetbrains.kotlin.utils.sure
import java.io.File import java.io.File
open class GeneratedFile<Target>( open class GeneratedFile(
val target: Target, val sourceFiles: Collection<File>,
val sourceFiles: Collection<File>, val outputFile: File
val outputFile: File
) )
class GeneratedJvmClass<Target> ( class GeneratedJvmClass (
target: Target,
sourceFiles: Collection<File>, sourceFiles: Collection<File>,
outputFile: File outputFile: File
) : GeneratedFile<Target>(target, sourceFiles, outputFile) { ) : GeneratedFile(sourceFiles, outputFile) {
val outputClass = LocalFileKotlinClass.create(outputFile).sure { val outputClass = LocalFileKotlinClass.create(outputFile).sure {
"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"
} }
@@ -16,9 +16,17 @@
package org.jetbrains.kotlin.compilerRunner package org.jetbrains.kotlin.compilerRunner
import org.jetbrains.kotlin.build.GeneratedFile
import org.jetbrains.kotlin.build.GeneratedJvmClass
import java.io.File import java.io.File
data class SimpleOutputItem(val sourceFiles: Collection<File>, val outputFile: File) { data class SimpleOutputItem(val sourceFiles: Collection<File>, val outputFile: File) {
override fun toString(): String = override fun toString(): String =
"$sourceFiles->$outputFile" "$sourceFiles->$outputFile"
} }
fun SimpleOutputItem.toGeneratedFile(): GeneratedFile =
when {
outputFile.name.endsWith(".class") -> GeneratedJvmClass(sourceFiles, outputFile)
else -> GeneratedFile(sourceFiles, outputFile)
}
@@ -114,7 +114,7 @@ open class IncrementalCacheImpl(
return CompilationResult.NO_CHANGES return CompilationResult.NO_CHANGES
} }
open fun saveFileToCache(generatedClass: GeneratedJvmClass<*>): CompilationResult { open fun saveFileToCache(generatedClass: GeneratedJvmClass): CompilationResult {
val sourceFiles: Collection<File> = generatedClass.sourceFiles val sourceFiles: Collection<File> = generatedClass.sourceFiles
val kotlinClass: LocalFileKotlinClass = generatedClass.outputClass val kotlinClass: LocalFileKotlinClass = generatedClass.outputClass
val className = kotlinClass.className val className = kotlinClass.className
@@ -77,13 +77,13 @@ fun makeCompileServices(
} }
fun updateIncrementalCache( fun updateIncrementalCache(
generatedFiles: List<GeneratedFile<*>>, generatedFiles: Iterable<GeneratedFile>,
cache: IncrementalCacheImpl cache: IncrementalCacheImpl
): CompilationResult { ): CompilationResult {
var changesInfo = CompilationResult.NO_CHANGES var changesInfo = CompilationResult.NO_CHANGES
for (generatedFile in generatedFiles) { for (generatedFile in generatedFiles) {
when { 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) generatedFile.outputFile.isModuleMappingFile() -> changesInfo += cache.saveModuleMappingToCache(generatedFile.sourceFiles, generatedFile.outputFile)
} }
} }
@@ -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.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.jetbrains.kotlin.compilerRunner.ArgumentUtils import org.jetbrains.kotlin.compilerRunner.*
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollector
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
import org.jetbrains.kotlin.config.IncrementalCompilation import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.multiproject.ArtifactChangesProvider import org.jetbrains.kotlin.incremental.multiproject.ArtifactChangesProvider
@@ -180,16 +178,16 @@ abstract class IncrementalCompilerRunner<
protected open fun markOutputDirty(caches: CacheManager, dirtySources: List<File>) { protected open fun markOutputDirty(caches: CacheManager, dirtySources: List<File>) {
} }
protected abstract fun compareAndUpdateCache(caches: CacheManager, generatedFiles: List<GeneratedFile<*>>): CompilationResult protected abstract fun compareAndUpdateCache(caches: CacheManager, generatedFiles: List<GeneratedFile>): CompilationResult
protected open fun preBuildHook(args: Args, compilationMode: CompilationMode) {} protected open fun preBuildHook(args: Args, compilationMode: CompilationMode) {}
protected open fun postCompilationHook(exitCode: ExitCode) {} protected open fun postCompilationHook(exitCode: ExitCode) {}
protected open fun additionalDirtyFiles(caches: CacheManager, generatedFiles: List<GeneratedFile<*>>): Iterable<File> = protected open fun additionalDirtyFiles(caches: CacheManager, generatedFiles: List<GeneratedFile>): Iterable<File> =
emptyList() emptyList()
protected abstract fun compileIncrementally(args: Args, caches: CacheManager, allKotlinSources: List<File>, compilationMode: CompilationMode, messageCollector: MessageCollector): ExitCode protected abstract fun compileIncrementally(args: Args, caches: CacheManager, allKotlinSources: List<File>, compilationMode: CompilationMode, messageCollector: MessageCollector): ExitCode
protected data class CompileChangedResults(val exitCode: ExitCode, val generatedFiles: List<GeneratedFile<TargetId>>) protected data class CompileChangedResults(val exitCode: ExitCode, val generatedFiles: List<GeneratedFile>)
protected sealed class CompilationMode { protected sealed class CompilationMode {
class Incremental(val dirtyFiles: Set<File>) : CompilationMode() class Incremental(val dirtyFiles: Set<File>) : CompilationMode()
@@ -334,7 +332,7 @@ class IncrementalJvmCompilerRunner(
} }
} }
override fun compareAndUpdateCache(caches: IncrementalJvmCachesManager, generatedFiles: List<GeneratedFile<*>>): CompilationResult = override fun compareAndUpdateCache(caches: IncrementalJvmCachesManager, generatedFiles: List<GeneratedFile>): CompilationResult =
updateIncrementalCache(generatedFiles, caches.platformCache) updateIncrementalCache(generatedFiles, caches.platformCache)
override fun compileIncrementally( override fun compileIncrementally(
@@ -358,7 +356,7 @@ class IncrementalJvmCompilerRunner(
val allSourcesToCompile = HashSet<File>() val allSourcesToCompile = HashSet<File>()
var exitCode = ExitCode.OK var exitCode = ExitCode.OK
val allGeneratedFiles = hashSetOf<GeneratedFile<TargetId>>() val allGeneratedFiles = hashSetOf<GeneratedFile>()
while (dirtySources.any()) { while (dirtySources.any()) {
markOutputDirty(caches, dirtySources) markOutputDirty(caches, dirtySources)
@@ -436,7 +434,7 @@ class IncrementalJvmCompilerRunner(
override fun additionalDirtyFiles( override fun additionalDirtyFiles(
caches: IncrementalJvmCachesManager, caches: IncrementalJvmCachesManager,
generatedFiles: List<GeneratedFile<*>> generatedFiles: List<GeneratedFile>
): Iterable<File> { ): Iterable<File> {
val cache = caches.platformCache val cache = caches.platformCache
val result = HashSet<File>() val result = HashSet<File>()
@@ -447,7 +445,7 @@ class IncrementalJvmCompilerRunner(
} }
for (generatedFile in generatedFiles) { for (generatedFile in generatedFiles) {
if (generatedFile !is GeneratedJvmClass<*>) continue if (generatedFile !is GeneratedJvmClass) continue
val outputClass = generatedFile.outputClass val outputClass = generatedFile.outputClass
@@ -511,14 +509,7 @@ class IncrementalJvmCompilerRunner(
reporter.report { "compiling with classpath: ${classpath.toList().sorted().joinToString()}" } reporter.report { "compiling with classpath: ${classpath.toList().sorted().joinToString()}" }
val compileServices = makeCompileServices(incrementalCaches, lookupTracker, compilationCanceledStatus) val compileServices = makeCompileServices(incrementalCaches, lookupTracker, compilationCanceledStatus)
val exitCode = compiler.exec(messageCollector, compileServices, args) val exitCode = compiler.exec(messageCollector, compileServices, args)
val generatedFiles = outputItemCollector.outputs.map { val generatedFiles = outputItemCollector.outputs.map(SimpleOutputItem::toGeneratedFile)
val outputItem = it.outputFile
val sourceFiles = it.sourceFiles
when (outputItem.extension) {
"class" -> GeneratedJvmClass(targetId, sourceFiles, outputItem)
else -> GeneratedFile(targetId, sourceFiles, outputItem)
}
}
reporter.reportCompileIteration(sourcesToCompile, exitCode) reporter.reportCompileIteration(sourcesToCompile, exitCode)
return CompileChangedResults(exitCode, generatedFiles) return CompileChangedResults(exitCode, generatedFiles)
} }
@@ -40,7 +40,7 @@ class InputsCache(
// generatedFiles can contain multiple entries with the same source file // 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 // for example Kapt3 IC will generate a .java stub and .class stub for each source file
fun registerOutputForSourceFiles(generatedFiles: List<GeneratedFile<*>>) { fun registerOutputForSourceFiles(generatedFiles: List<GeneratedFile>) {
val sourceToOutput = MultiMap<File, File>() val sourceToOutput = MultiMap<File, File>()
for (generatedFile in generatedFiles) { for (generatedFile in generatedFiles) {
@@ -22,7 +22,6 @@ import com.intellij.openapi.util.io.FileUtil
import com.intellij.util.containers.ContainerUtil import com.intellij.util.containers.ContainerUtil
import com.intellij.util.containers.MultiMap import com.intellij.util.containers.MultiMap
import gnu.trove.THashSet import gnu.trove.THashSet
import jdk.nashorn.internal.lookup.Lookup
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
@@ -41,17 +40,13 @@ import org.jetbrains.jps.model.module.JpsModule
import org.jetbrains.kotlin.build.GeneratedFile import org.jetbrains.kotlin.build.GeneratedFile
import org.jetbrains.kotlin.build.GeneratedJvmClass import org.jetbrains.kotlin.build.GeneratedJvmClass
import org.jetbrains.kotlin.build.JvmBuildMetaInfo 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.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation 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.CompilerMessageSeverity.* import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil import org.jetbrains.kotlin.cli.common.messages.MessageCollectorUtil
import org.jetbrains.kotlin.compilerRunner.JpsCompilerEnvironment import org.jetbrains.kotlin.compilerRunner.*
import org.jetbrains.kotlin.compilerRunner.JpsKotlinCompilerRunner
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollector
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
import org.jetbrains.kotlin.config.CompilerRunnerConstants import org.jetbrains.kotlin.config.CompilerRunnerConstants
import org.jetbrains.kotlin.config.CompilerRunnerConstants.INTERNAL_ERROR_PREFIX import org.jetbrains.kotlin.config.CompilerRunnerConstants.INTERNAL_ERROR_PREFIX
import org.jetbrains.kotlin.config.IncrementalCompilation import org.jetbrains.kotlin.config.IncrementalCompilation
@@ -311,9 +306,7 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
return OK return OK
} }
@Suppress("REIFIED_TYPE_UNSAFE_SUBSTITUTION") updateJavaMappings(chunk, context, dirtyFilesHolder, filesToCompile, generatedFiles, incrementalCaches)
val generatedClasses = generatedFiles.filterIsInstance<GeneratedJvmClass<ModuleBuildTarget>>()
updateJavaMappings(chunk, compilationErrors, context, dirtyFilesHolder, filesToCompile, generatedClasses, incrementalCaches)
if (!IncrementalCompilation.isEnabled()) { if (!IncrementalCompilation.isEnabled()) {
return OK return OK
@@ -321,7 +314,9 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
context.checkCanceled() 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) updateLookupStorage(chunk, lookupTracker, dataManager, dirtyFilesHolder, filesToCompile)
if (isChunkRebuilding) { if (isChunkRebuilding) {
@@ -517,7 +512,7 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
private fun getGeneratedFiles( private fun getGeneratedFiles(
chunk: ModuleChunk, chunk: ModuleChunk,
outputItemCollector: OutputItemsCollectorImpl outputItemCollector: OutputItemsCollectorImpl
): List<GeneratedFile<ModuleBuildTarget>> { ): Map<ModuleBuildTarget, List<GeneratedFile>> {
// If there's only one target, this map is empty: get() always returns null, and the representativeTarget will be used below // If there's only one target, this map is empty: get() always returns null, and the representativeTarget will be used below
val sourceToTarget = HashMap<File, ModuleBuildTarget>() val sourceToTarget = HashMap<File, ModuleBuildTarget>()
if (chunk.targets.size > 1) { if (chunk.targets.size > 1) {
@@ -528,34 +523,21 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
} }
} }
val result = ArrayList<GeneratedFile<ModuleBuildTarget>>()
val representativeTarget = chunk.representativeTarget() val representativeTarget = chunk.representativeTarget()
for (outputItem in outputItemCollector.outputs) { fun SimpleOutputItem.target() =
val sourceFiles = outputItem.sourceFiles sourceFiles.firstOrNull()?.let { sourceToTarget[it] } ?:
val outputFile = outputItem.outputFile chunk.targets.singleOrNull { it.outputDir?.let { outputFile.startsWith(it) } ?: false } ?:
val target = representativeTarget
sourceFiles.firstOrNull()?.let { sourceToTarget[it] } ?:
chunk.targets.singleOrNull { it.outputDir?.let { outputFile.startsWith(it) } ?: false } ?:
representativeTarget
if (outputFile.name.endsWith(".class")) { return outputItemCollector.outputs.groupBy(SimpleOutputItem::target, SimpleOutputItem::toGeneratedFile)
result.add(GeneratedJvmClass(target, sourceFiles, outputFile))
}
else {
result.add(GeneratedFile<ModuleBuildTarget>(target, sourceFiles, outputFile))
}
}
return result
} }
private fun updateJavaMappings( private fun updateJavaMappings(
chunk: ModuleChunk, chunk: ModuleChunk,
compilationErrors: Boolean,
context: CompileContext, context: CompileContext,
dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>, dirtyFilesHolder: DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget>,
filesToCompile: MultiMap<ModuleBuildTarget, File>, filesToCompile: MultiMap<ModuleBuildTarget, File>,
generatedClasses: List<GeneratedJvmClass<ModuleBuildTarget>>, outputItems: Map<ModuleBuildTarget, Iterable<GeneratedFile>>,
incrementalCaches: Map<ModuleBuildTarget, JpsIncrementalCacheImpl> incrementalCaches: Map<ModuleBuildTarget, JpsIncrementalCacheImpl>
) { ) {
val previousMappings = context.projectDescriptor.dataManager.mappings val previousMappings = context.projectDescriptor.dataManager.mappings
@@ -568,8 +550,8 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
files files
} }
fun getOldSourceFiles(generatedClass: GeneratedJvmClass<ModuleBuildTarget>): Set<File> { fun getOldSourceFiles(target: ModuleBuildTarget, generatedClass: GeneratedJvmClass): Set<File> {
val cache = incrementalCaches[generatedClass.target] ?: return emptySet() val cache = incrementalCaches[target] ?: return emptySet()
val className = generatedClass.outputClass.className val className = generatedClass.outputClass.className
if (!cache.isMultifileFacade(className)) return emptySet() if (!cache.isMultifileFacade(className)) return emptySet()
@@ -578,65 +560,34 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
return previousMappings.getClassSources(name)?.toSet() ?: emptySet() return previousMappings.getClassSources(name)?.toSet() ?: emptySet()
} }
for (generatedClass in generatedClasses) { for ((target, outputs) in outputItems) {
val sourceFiles = THashSet(FileUtil.FILE_HASHING_STRATEGY) for (output in outputs) {
sourceFiles.addAll(getOldSourceFiles(generatedClass)) if (output !is GeneratedJvmClass) continue
sourceFiles.removeAll(targetDirtyFiles[generatedClass.target] ?: emptySet())
sourceFiles.addAll(generatedClass.sourceFiles)
callback.associate( val sourceFiles = THashSet(FileUtil.FILE_HASHING_STRATEGY)
FileUtil.toSystemIndependentName(generatedClass.outputFile.canonicalPath), sourceFiles.addAll(getOldSourceFiles(target, output))
sourceFiles.map { FileUtil.toSystemIndependentName(it.canonicalPath) }, sourceFiles.removeAll(targetDirtyFiles[target] ?: emptySet())
ClassReader(generatedClass.outputClass.fileContents) sourceFiles.addAll(output.sourceFiles)
)
}
val allCompiled = filesToCompile.values() callback.associate(
val successfullyCompiled = if (compilationErrors) listOf<File>() else allCompiled FileUtil.toSystemIndependentName(output.outputFile.canonicalPath),
sourceFiles.map { FileUtil.toSystemIndependentName(it.canonicalPath) },
JavaBuilderUtil.registerFilesToCompile(context, allCompiled) ClassReader(output.outputClass.fileContents)
JavaBuilderUtil.registerSuccessfullyCompiled(context, successfullyCompiled) )
}
private fun registerOutputItems(outputConsumer: ModuleLevelBuilder.OutputConsumer, generatedFiles: List<GeneratedFile<ModuleBuildTarget>>) {
for (generatedFile in generatedFiles) {
outputConsumer.registerOutputFile(generatedFile.target, generatedFile.outputFile, generatedFile.sourceFiles.map { it.path })
}
}
private fun updateKotlinIncrementalCache(
compilationErrors: Boolean,
incrementalCaches: Map<ModuleBuildTarget, JpsIncrementalCacheImpl>,
generatedFiles: List<GeneratedFile<ModuleBuildTarget>>
): 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<ModuleBuildTarget>) {
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
} }
} }
return changesInfo val allCompiled = filesToCompile.values()
JavaBuilderUtil.registerFilesToCompile(context, allCompiled)
JavaBuilderUtil.registerSuccessfullyCompiled(context, allCompiled)
}
private fun registerOutputItems(outputConsumer: OutputConsumer, outputItems: Map<ModuleBuildTarget, List<GeneratedFile>>) {
for ((target, outputs) in outputItems) {
for (output in outputs) {
outputConsumer.registerOutputFile(target, output.outputFile, output.sourceFiles.map { it.path })
}
}
} }
private fun updateLookupStorage( private fun updateLookupStorage(