diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrLink.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrLink.kt index 28bb869cd1d..528755a5f0f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrLink.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrLink.kt @@ -14,6 +14,7 @@ import org.gradle.api.file.FileTree import org.gradle.api.logging.Logger import org.gradle.api.model.ObjectFactory import org.gradle.api.tasks.* +import org.gradle.work.InputChanges import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments import org.jetbrains.kotlin.compilerRunner.GradleCompilerEnvironment import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner @@ -35,7 +36,6 @@ import org.jetbrains.kotlin.gradle.tasks.SourceRoots import org.jetbrains.kotlin.gradle.utils.getAllDependencies import org.jetbrains.kotlin.gradle.utils.getCacheDirectory import org.jetbrains.kotlin.gradle.utils.getDependenciesCacheDirectories -import org.jetbrains.kotlin.incremental.ChangedFiles import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics import java.io.File import javax.inject.Inject @@ -94,7 +94,7 @@ abstract class KotlinJsIrLink @Inject constructor( return !entryModule.get().asFile.exists() } - override fun callCompilerAsync(args: K2JSCompilerArguments, sourceRoots: SourceRoots, changedFiles: ChangedFiles) { + override fun callCompilerAsync(args: K2JSCompilerArguments, sourceRoots: SourceRoots, inputChanges: InputChanges) { KotlinBuildStatsService.applyIfInitialised { it.report(BooleanMetrics.JS_IR_INCREMENTAL, incrementalJsIr) } @@ -125,7 +125,7 @@ abstract class KotlinJsIrLink @Inject constructor( it.normalize().absolutePath } } - super.callCompilerAsync(args, sourceRoots, changedFiles) + super.callCompilerAsync(args, sourceRoots, inputChanges) } private fun visitCompilation( diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinCompileCommon.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinCompileCommon.kt index eb10ae85abb..4569690723a 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinCompileCommon.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinCompileCommon.kt @@ -20,6 +20,7 @@ import org.gradle.api.Project import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.provider.Provider import org.gradle.api.tasks.* +import org.gradle.work.InputChanges import org.jetbrains.kotlin.cli.common.arguments.K2MetadataCompilerArguments import org.jetbrains.kotlin.compilerRunner.GradleCompilerEnvironment import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl @@ -35,7 +36,6 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinMetadataCompilationData import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.refinesClosure import org.jetbrains.kotlin.gradle.plugin.sources.resolveAllDependsOnSourceSets -import org.jetbrains.kotlin.incremental.ChangedFiles import java.io.File import javax.inject.Inject @@ -116,7 +116,7 @@ abstract class KotlinCompileCommon @Inject constructor( @get:Internal internal val expectActualLinker = objects.property(Boolean::class.java) - override fun callCompilerAsync(args: K2MetadataCompilerArguments, sourceRoots: SourceRoots, changedFiles: ChangedFiles) { + override fun callCompilerAsync(args: K2MetadataCompilerArguments, sourceRoots: SourceRoots, inputChanges: InputChanges) { val messageCollector = GradlePrintingMessageCollector(logger, args.allWarningsAsErrors) val outputItemCollector = OutputItemsCollectorImpl() val compilerRunner = compilerRunner.get() 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 e62493eef74..8919fa0186c 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 @@ -396,11 +396,7 @@ abstract class AbstractKotlinCompile : AbstractKotl sourceRoots.log(this.name, logger) val args = prepareCompilerArguments() taskBuildDirectory.get().asFile.mkdirs() - callCompilerAsync( - args, - sourceRoots, - getChangedFiles(inputChanges, incrementalProps) - ) + callCompilerAsync(args, sourceRoots, inputChanges) } protected fun getChangedFiles( @@ -432,7 +428,7 @@ abstract class AbstractKotlinCompile : AbstractKotl * Compiler might be executed asynchronously. Do not do anything requiring end of compilation after this function is called. * @see [GradleKotlinCompilerWork] */ - internal abstract fun callCompilerAsync(args: T, sourceRoots: SourceRoots, changedFiles: ChangedFiles) + internal abstract fun callCompilerAsync(args: T, sourceRoots: SourceRoots, inputChanges: InputChanges) @get:Input internal val multiPlatformEnabled: Property = objects.property(Boolean::class.java) @@ -679,7 +675,7 @@ abstract class KotlinCompile @Inject constructor( override fun getSourceRoots(): SourceRoots.ForJvm = jvmSourceRoots - override fun callCompilerAsync(args: K2JVMCompilerArguments, sourceRoots: SourceRoots, changedFiles: ChangedFiles) { + override fun callCompilerAsync(args: K2JVMCompilerArguments, sourceRoots: SourceRoots, inputChanges: InputChanges) { sourceRoots as SourceRoots.ForJvm validateKotlinAndJavaHasSameTargetCompatibility(args) @@ -691,15 +687,12 @@ abstract class KotlinCompile @Inject constructor( val icEnv = if (isIncrementalCompilationEnabled()) { val classpathChanges = when { !classpathSnapshotProperties.useClasspathSnapshot.get() -> ClasspathChanges.NotAvailable.ClasspathSnapshotIsDisabled - else -> when (changedFiles) { - is ChangedFiles.Known -> getClasspathChanges(changedFiles) - is ChangedFiles.Unknown -> ClasspathChanges.NotAvailable.ForNonIncrementalRun - is ChangedFiles.Dependencies -> error("Unexpected type: ${changedFiles.javaClass.name}") - } + inputChanges.isIncremental -> getClasspathChanges(inputChanges) + else -> ClasspathChanges.NotAvailable.ForNonIncrementalRun } logger.info(USING_JVM_INCREMENTAL_COMPILATION_MESSAGE) IncrementalCompilationEnvironment( - changedFiles = changedFiles, + changedFiles = getChangedFiles(inputChanges, incrementalProps), classpathChanges = classpathChanges, workingDir = taskBuildDirectory.get().asFile, usePreciseJavaTracking = usePreciseJavaTracking, @@ -797,29 +790,17 @@ abstract class KotlinCompile @Inject constructor( return super.source(*sources) } - private fun getClasspathChanges(knownChangedFiles: ChangedFiles.Known): ClasspathChanges { - // Find current snapshot files that have been changed (added or modified) - val currentSnapshotFiles = classpathSnapshotProperties.classpathSnapshot.files - val addedOrModifiedFiles = knownChangedFiles.modified.toSet() - val (changedCurrentSnapshotFiles, unchangedCurrentSnapshotFiles) = currentSnapshotFiles.partition { it in addedOrModifiedFiles } - - // Find previous snapshot files that have been changed (modified or removed) + private fun getClasspathChanges(@Suppress("UNUSED_PARAMETER") inputChanges: InputChanges): ClasspathChanges { + val currentSnapshotFiles = classpathSnapshotProperties.classpathSnapshot.files.toList() val previousSnapshotFiles = getClasspathSnapshotFilesInDir(classpathSnapshotProperties.classpathSnapshotDir.get().asFile) - var unchangedSnapshotIndex = 0 - var unchangedSnapshot: ByteArray? = unchangedCurrentSnapshotFiles.getOrNull(unchangedSnapshotIndex)?.readBytes() - val changedPreviousSnapshotFiles = previousSnapshotFiles.filter { - if (unchangedSnapshot != null && it.readBytes().contentEquals(unchangedSnapshot)) { - unchangedSnapshotIndex++ - unchangedSnapshot = unchangedCurrentSnapshotFiles.getOrNull(unchangedSnapshotIndex)?.readBytes() - false - } else true - } - // Compute changes for the changed snapshot files only, ignoring unchanged ones - val changedCurrentSnapshot = ClasspathSnapshotSerializer.load(changedCurrentSnapshotFiles) - val changedPreviousSnapshot = ClasspathSnapshotSerializer.load(changedPreviousSnapshotFiles) + // TODO: Compute changes for the changed snapshot files only, ignoring unchanged ones. + // We'll need to be careful when the classpath contains duplicate classes, as we'll need to look at the entire classpath in order to + // detect them. + val currentSnapshot = ClasspathSnapshotSerializer.load(currentSnapshotFiles) + val previousSnapshot = ClasspathSnapshotSerializer.load(previousSnapshotFiles) - return ClasspathChangesComputer.compute(changedCurrentSnapshot, changedPreviousSnapshot) + return ClasspathChangesComputer.compute(currentSnapshot, previousSnapshot) } /** @@ -1095,7 +1076,7 @@ abstract class Kotlin2JsCompile @Inject constructor( override val incrementalProps: List get() = super.incrementalProps + listOf(friendDependencies) - override fun callCompilerAsync(args: K2JSCompilerArguments, sourceRoots: SourceRoots, changedFiles: ChangedFiles) { + override fun callCompilerAsync(args: K2JSCompilerArguments, sourceRoots: SourceRoots, inputChanges: InputChanges) { sourceRoots as SourceRoots.KotlinOnly logger.debug("Calling compiler") @@ -1130,7 +1111,7 @@ abstract class Kotlin2JsCompile @Inject constructor( val icEnv = if (isIncrementalCompilationEnabled()) { logger.info(USING_JS_INCREMENTAL_COMPILATION_MESSAGE) IncrementalCompilationEnvironment( - changedFiles, + getChangedFiles(inputChanges, incrementalProps), ClasspathChanges.NotAvailable.ForJSCompiler, taskBuildDirectory.get().asFile, multiModuleICSettings = multiModuleICSettings