diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/ChangedFiles.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/ChangedFiles.kt new file mode 100644 index 00000000000..87086b708b1 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/ChangedFiles.kt @@ -0,0 +1,22 @@ +package org.jetbrains.kotlin.gradle.tasks + +import org.gradle.api.tasks.incremental.IncrementalTaskInputs +import java.io.File +import java.util.* + +internal sealed class ChangedFiles { + class Known(val modified: List, val removed: List) : ChangedFiles() + class Unknown : ChangedFiles() +} + +internal fun ChangedFiles(taskInputs: IncrementalTaskInputs): ChangedFiles { + if (!taskInputs.isIncremental) return ChangedFiles.Unknown() + + val modified = ArrayList() + val removed = ArrayList() + + taskInputs.outOfDate { modified.add(it.file) } + taskInputs.removed { removed.add(it.file) } + + return ChangedFiles.Known(modified, removed) +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt index e40b5aae4fc..2fb5ca37038 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt @@ -77,31 +77,29 @@ abstract class AbstractKotlinCompile() : AbstractCo @TaskAction fun execute(inputs: IncrementalTaskInputs): Unit { - logger.kotlinDebug("all sources ${getSource().joinToString { it.path }}") - logger.kotlinDebug("is incremental == ${inputs.isIncremental}") - val modified = arrayListOf() - val removed = arrayListOf() - if (inputs.isIncremental) { - inputs.outOfDate { modified.add(it.file) } - inputs.removed { removed.add(it.file) } - } - logger.kotlinDebug("modified ${modified.joinToString { it.path }}") - logger.kotlinDebug("removed ${removed.joinToString { it.path }}") - val sources = getKotlinSources() - if (sources.isEmpty()) { + val allKotlinSources = getKotlinSources() + logger.kotlinDebug { "all kotlin sources: ${filesToString(allKotlinSources)}" } + + if (allKotlinSources.isEmpty()) { logger.kotlinDebug { "No Kotlin files found, skipping Kotlin compiler task" } return } val args = populateCompilerArguments() compilerCalled = true - callCompiler(args, sources, inputs.isIncremental, modified, removed) + callCompiler(args, allKotlinSources, ChangedFiles(inputs)) } - private fun getKotlinSources(): List = (getSource() as Iterable).filter { it.isKotlinFile() } + private fun getKotlinSources(): List = (getSource() as Iterable).filter(File::isKotlinFile) - protected abstract fun callCompiler(args: T, allKotlinSources: List, isIncremental: Boolean, modified: List, removed: List) + internal abstract fun callCompiler(args: T, allKotlinSources: List, changedFiles: ChangedFiles) + internal fun relativePathOrCanonical(file: File): String = + file.relativeToOrNull(project.rootProject.projectDir)?.path + ?: file.canonicalPath + + internal fun filesToString(files: Iterable) = + "[" + files.map { relativePathOrCanonical(it) }.sorted().joinToString(separator = ", \n") + "]" } open class KotlinCompile : AbstractKotlinCompile(), KotlinJvmCompile { @@ -175,9 +173,8 @@ open class KotlinCompile : AbstractKotlinCompile(), Kotl return args } - override fun callCompiler(args: K2JVMCompilerArguments, allKotlinSources: List, isIncrementalRequested: Boolean, modified: List, removed: List) { + override fun callCompiler(args: K2JVMCompilerArguments, allKotlinSources: List, changedFiles: ChangedFiles) { val outputDir = destinationDir - var currentRemoved = removed.filter { it.isKotlinFile() } val logAction = { logStr: String -> logger.kotlinInfo(logStr) } val relativePathOrCanonical = { file: File -> relativePathOrCanonical(file) } @@ -221,7 +218,7 @@ open class KotlinCompile : AbstractKotlinCompile(), Kotl return ChangesEither.Known(symbols, fqNames) } - fun calculateSourcesToCompile(javaFilesProcessor: ChangedJavaFilesProcessor, caches: IncrementalCachesManager, lastBuildInfo: BuildInfo?): Pair, Boolean> { + fun calculateSourcesToCompile(javaFilesProcessor: ChangedJavaFilesProcessor, caches: IncrementalCachesManager, lastBuildInfo: BuildInfo?, changedFiles: ChangedFiles): Pair, Boolean> { fun rebuild(reason: String): Pair, Boolean> { logger.kotlinInfo("Non-incremental compilation will be performed: $reason") caches.clean() @@ -230,15 +227,15 @@ open class KotlinCompile : AbstractKotlinCompile(), Kotl } if (!incremental) return rebuild("incremental compilation is not enabled") - if (!isIncrementalRequested) return rebuild("inputs' changes are unknown (first or clean build)") + if (changedFiles !is ChangedFiles.Known) return rebuild("inputs' changes are unknown (first or clean build)") - val removedClassFiles = removed.filter(File::isClassFile) + val removedClassFiles = changedFiles.removed.filter(File::isClassFile) if (removedClassFiles.any()) return rebuild("Removed class files: ${filesToString(removedClassFiles)}") - val modifiedClassFiles = modified.filter(File::isClassFile) + val modifiedClassFiles = changedFiles.modified.filter(File::isClassFile) if (modifiedClassFiles.any()) return rebuild("Modified class files: ${filesToString(modifiedClassFiles)}") - val modifiedClasspathEntries = modified.filter { it in classpath } + val modifiedClasspathEntries = changedFiles.modified.filter { it in classpath } val classpathChanges = getClasspathChanges(modifiedClasspathEntries, lastBuildInfo) if (classpathChanges is ChangesEither.Unknown) { return rebuild("could not get changes from modified classpath entries: ${filesToString(modifiedClasspathEntries)}") @@ -247,15 +244,15 @@ open class KotlinCompile : AbstractKotlinCompile(), Kotl throw AssertionError("Unknown implementation of ChangesEither: ${classpathChanges.javaClass}") } val javaFilesDiff = FileCollectionDiff( - newOrModified = modified.filter { it.isJavaFile() }, - removed = removed.filter { it.isJavaFile() }) + newOrModified = changedFiles.modified.filter(File::isJavaFile), + removed = changedFiles.removed.filter(File::isJavaFile)) val javaFilesChanges = javaFilesProcessor.process(javaFilesDiff) val affectedJavaSymbols = when (javaFilesChanges) { is ChangesEither.Known -> javaFilesChanges.lookupSymbols is ChangesEither.Unknown -> return rebuild("Could not get changes for java files") } - val dirtyFiles = modified.filter { it.isKotlinFile() }.toMutableSet() + val dirtyFiles = changedFiles.modified.filter(File::isKotlinFile).toMutableSet() val lookupSymbols = HashSet() lookupSymbols.addAll(affectedJavaSymbols) lookupSymbols.addAll(classpathChanges.lookupSymbols) @@ -299,8 +296,9 @@ open class KotlinCompile : AbstractKotlinCompile(), Kotl val caches = IncrementalCachesManager(targetId, cacheDirectory, outputDir) // TODO: decide what to do if no files are considered dirty - rebuild or skip the module - var (sourcesToCompile, isIncrementalDecided) = calculateSourcesToCompile(javaFilesProcessor, caches, lastBuildInfo) - compileIncrementally(allGeneratedFiles, args, caches, currentRemoved, isIncrementalDecided, javaFilesProcessor, logAction, lookupTracker, outputDir, relativePathOrCanonical, allKotlinSources, sourcesToCompile, targetId) + var (sourcesToCompile, isIncrementalDecided) = calculateSourcesToCompile(javaFilesProcessor, caches, lastBuildInfo, changedFiles) + val currentRemoved = (changedFiles as? ChangedFiles.Known)?.removed?.filter(File::isKotlinFile) ?: emptyList() + compileIncrementally(args, caches, currentRemoved, isIncrementalDecided, javaFilesProcessor, logAction, lookupTracker, outputDir, relativePathOrCanonical, allKotlinSources, sourcesToCompile, targetId) } private fun compileIncrementally( @@ -424,13 +422,6 @@ open class KotlinCompile : AbstractKotlinCompile(), Kotl processCompilerExitCode(exitCode) } - private fun relativePathOrCanonical(file: File): String = - file.relativeToOrNull(project.rootProject.projectDir)?.path - ?: file.canonicalPath - - private fun filesToString(files: Iterable) = - "[" + files.map { relativePathOrCanonical(it) }.sorted().joinToString(separator = ", \n") + "]" - private fun cleanupOnError() { logger.kotlinInfo("deleting $destinationDir on error") destinationDir.deleteRecursively() @@ -639,7 +630,7 @@ open class Kotlin2JsCompile() : AbstractKotlinCompile(), return args } - override fun callCompiler(args: K2JSCompilerArguments, allKotlinSources: List, isIncremental: Boolean, modified: List, removed: List) { + override fun callCompiler(args: K2JSCompilerArguments, allKotlinSources: List, changedFiles: ChangedFiles) { val messageCollector = GradleMessageCollector(logger) logger.debug("Calling compiler") destinationDir.mkdirs()