From 30f3622b277da99abe909f5614fb2e94350de6cd Mon Sep 17 00:00:00 2001 From: Alexey Tsvetkov Date: Tue, 10 Jul 2018 15:18:32 +0300 Subject: [PATCH] Implement inter-project JS IC with Gradle #KT-25025 fixed --- .../daemon/common/IncrementalModuleInfo.kt | 4 +- .../kotlin/daemon/CompileServiceImpl.kt | 11 +- .../incremental/IncrementalCompilerRunner.kt | 12 +- .../IncrementalJsCompilerRunner.kt | 45 ++- .../IncrementalJvmCompilerRunner.kt | 75 +--- .../incremental/changesDetectionUtils.kt | 65 ++++ .../multiproject/ModulesApiHistory.kt | 21 +- .../ModulesApiHistoryAndroidTest.kt | 3 +- .../jetbrains/kotlin/gradle/BaseGradleIT.kt | 5 +- .../IncrementalCompilationMultiProjectIT.kt | 367 ++++++++++-------- .../kotlin/gradle/Kotlin2JsGradlePluginIT.kt | 4 +- .../app/build-js.gradle | 7 + .../app/src/main/{java => kotlin}/foo/AA.kt | 0 .../app/src/main/kotlin/foo/AAA.kt | 12 + .../app/src/main/{java => kotlin}/foo/BB.kt | 0 .../src/main/{java => kotlin}/foo/FooDummy.kt | 0 .../main/{java => kotlin}/foo/fooCallUseAB.kt | 0 .../src/main/{java => kotlin}/foo/fooUseA.kt | 0 .../src/main/{java => kotlin}/foo/fooUseAA.kt | 0 .../src/main/{java => kotlin}/foo/fooUseB.kt | 0 .../src/main/{java => kotlin}/foo/fooUseBB.kt | 0 .../lib/build-js.gradle | 6 + .../lib/src/main/{java => kotlin}/bar/A.kt | 0 .../lib/src/main/{java => kotlin}/bar/B.kt | 0 .../src/main/{java => kotlin}/bar/BarDummy.kt | 0 .../src/main/{java => kotlin}/bar/barUseA.kt | 0 .../src/main/{java => kotlin}/bar/barUseAB.kt | 1 + .../src/main/{java => kotlin}/bar/barUseB.kt | 0 .../GradleKotlinCompilerRunner.kt | 37 +- .../jetbrains/kotlin/gradle/tasks/Tasks.kt | 4 +- 30 files changed, 408 insertions(+), 271 deletions(-) create mode 100644 compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/changesDetectionUtils.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/build-js.gradle rename libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/{java => kotlin}/foo/AA.kt (100%) create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/kotlin/foo/AAA.kt rename libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/{java => kotlin}/foo/BB.kt (100%) rename libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/{java => kotlin}/foo/FooDummy.kt (100%) rename libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/{java => kotlin}/foo/fooCallUseAB.kt (100%) rename libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/{java => kotlin}/foo/fooUseA.kt (100%) rename libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/{java => kotlin}/foo/fooUseAA.kt (100%) rename libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/{java => kotlin}/foo/fooUseB.kt (100%) rename libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/{java => kotlin}/foo/fooUseBB.kt (100%) create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/build-js.gradle rename libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/{java => kotlin}/bar/A.kt (100%) rename libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/{java => kotlin}/bar/B.kt (100%) rename libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/{java => kotlin}/bar/BarDummy.kt (100%) rename libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/{java => kotlin}/bar/barUseA.kt (100%) rename libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/{java => kotlin}/bar/barUseAB.kt (70%) rename libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/{java => kotlin}/bar/barUseB.kt (100%) diff --git a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/IncrementalModuleInfo.kt b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/IncrementalModuleInfo.kt index 1848e622986..6f1eeb29816 100644 --- a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/IncrementalModuleInfo.kt +++ b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/IncrementalModuleInfo.kt @@ -23,7 +23,9 @@ class IncrementalModuleInfo( val projectRoot: File, val dirToModule: Map, val nameToModules: Map>, - val jarToClassListFile: Map + val jarToClassListFile: Map, + // only for js + val jarToModule: Map ) : Serializable { companion object { private const val serialVersionUID = 0L diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt index d503b07a00d..6dae46fe948 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt @@ -52,6 +52,7 @@ import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumer import org.jetbrains.kotlin.incremental.parsing.classesFqNames import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistoryAndroid +import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistoryJs import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistoryJvm import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents import org.jetbrains.kotlin.modules.Module @@ -475,8 +476,14 @@ class CompileServiceImpl( incrementalCompilationOptions.customCacheVersionFileName, workingDir, enabled = true) - - val compiler = IncrementalJsCompilerRunner(workingDir, versions, reporter) + val modulesApiHistory = ModulesApiHistoryJs(incrementalCompilationOptions.modulesInfo) + val compiler = IncrementalJsCompilerRunner( + workingDir = workingDir, + cacheVersions = versions, + reporter = reporter, + buildHistoryFile = incrementalCompilationOptions.multiModuleICSettings.buildHistoryFile, + modulesApiHistory = modulesApiHistory + ) return compiler.compile(allKotlinFiles, args, compilerMessageCollector, changedFiles) } diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt index e5856ae97b6..c936aae5cf1 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt @@ -41,6 +41,7 @@ abstract class IncrementalCompilerRunner< cacheDirName: String, protected val cacheVersions: List, protected val reporter: ICReporter, + private val buildHistoryFile: File, private val localStateDirs: Collection = emptyList() ) { @@ -299,11 +300,20 @@ abstract class IncrementalCompilerRunner< open fun runWithNoDirtyKotlinSources(caches: CacheManager): Boolean = false - protected open fun processChangesAfterBuild( + private fun processChangesAfterBuild( compilationMode: CompilationMode, currentBuildInfo: BuildInfo, dirtyData: DirtyData ) { + val prevDiffs = BuildDiffsStorage.readFromFile(buildHistoryFile, reporter)?.buildDiffs ?: emptyList() + val newDiff = if (compilationMode is CompilationMode.Incremental) { + BuildDifference(currentBuildInfo.startTS, true, dirtyData) + } else { + val emptyDirtyData = DirtyData() + BuildDifference(currentBuildInfo.startTS, false, emptyDirtyData) + } + + BuildDiffsStorage.writeToFile(buildHistoryFile, BuildDiffsStorage(prevDiffs + newDiff), reporter) } companion object { diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJsCompilerRunner.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJsCompilerRunner.kt index fa739833b98..50ec20cd20b 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJsCompilerRunner.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJsCompilerRunner.kt @@ -16,7 +16,6 @@ package org.jetbrains.kotlin.incremental -import com.intellij.openapi.util.io.FileUtil import org.jetbrains.kotlin.build.GeneratedFile import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments @@ -27,6 +26,8 @@ import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.incremental.components.ExpectActualTracker import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.js.* +import org.jetbrains.kotlin.incremental.multiproject.EmptyModulesApiHistory +import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistory import java.io.File fun makeJsIncrementally( @@ -40,9 +41,13 @@ fun makeJsIncrementally( val versions = commonCacheVersions(cachesDir, isIncremental) + standaloneCacheVersion(cachesDir, isIncremental) val allKotlinFiles = sourceRoots.asSequence().flatMap { it.walk() } .filter { it.isFile && it.extension.equals("kt", ignoreCase = true) }.toList() + val buildHistoryFile = File(cachesDir, "build-history.bin") withJsIC { - val compiler = IncrementalJsCompilerRunner(cachesDir, versions, reporter) + val compiler = IncrementalJsCompilerRunner( + cachesDir, versions, reporter, + buildHistoryFile = buildHistoryFile, + modulesApiHistory = EmptyModulesApiHistory) compiler.compile(allKotlinFiles, args, messageCollector, providedChangedFiles = null) } } @@ -61,12 +66,15 @@ inline fun withJsIC(fn: () -> R): R { class IncrementalJsCompilerRunner( workingDir: File, cacheVersions: List, - reporter: ICReporter + reporter: ICReporter, + buildHistoryFile: File, + private val modulesApiHistory: ModulesApiHistory ) : IncrementalCompilerRunner( workingDir, "caches-js", cacheVersions, - reporter + reporter, + buildHistoryFile = buildHistoryFile ) { override fun isICEnabled(): Boolean = IncrementalCompilation.isEnabledForJs() @@ -78,21 +86,28 @@ class IncrementalJsCompilerRunner( File(args.outputFile).parentFile override fun calculateSourcesToCompile(caches: IncrementalJsCachesManager, changedFiles: ChangedFiles.Known, args: K2JSCompilerArguments): CompilationMode { - if (BuildInfo.read(lastBuildInfoFile) == null) return CompilationMode.Rebuild { "No information on previous build" } - - val libs = (args.libraries ?: "").split(File.pathSeparator).mapTo(HashSet()) { File(it) } - val libsDirs = libs.filter { it.isDirectory } - - val changedLib = changedFiles.allAsSequence.find { it in libs } - ?: changedFiles.allAsSequence.find { changedFile -> - libsDirs.any { libDir -> FileUtil.isAncestor(libDir, changedFile, true) } - } - - if (changedLib != null) return CompilationMode.Rebuild { "Library has been changed: $changedLib" } + val lastBuildInfo = BuildInfo.read(lastBuildInfoFile) + ?: return CompilationMode.Rebuild { "No information on previous build" } val dirtyFiles = DirtyFilesContainer(caches, reporter) initDirtyFiles(dirtyFiles, changedFiles) + val libs = (args.libraries ?: "").split(File.pathSeparator).map { File(it) } + val classpathChanges = getClasspathChanges(libs, changedFiles, lastBuildInfo, modulesApiHistory, reporter) + + @Suppress("UNUSED_VARIABLE") // for sealed when + val unused = when (classpathChanges) { + is ChangesEither.Unknown -> return CompilationMode.Rebuild { + // todo: we can recompile all files incrementally (not cleaning caches), so rebuild won't propagate + "Could not get classpath's changes${classpathChanges.reason?.let { ": $it" }}" + } + is ChangesEither.Known -> { + dirtyFiles.addByDirtySymbols(classpathChanges.lookupSymbols) + dirtyFiles.addByDirtyClasses(classpathChanges.fqNames) + } + } + + val removedClassesChanges = getRemovedClassesChanges(caches, changedFiles) dirtyFiles.addByDirtySymbols(removedClassesChanges.dirtyLookupSymbols) dirtyFiles.addByDirtyClasses(removedClassesChanges.dirtyClassesFqNames) 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 ff05efdebf8..8b432bf078c 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 @@ -104,7 +104,7 @@ class IncrementalJvmCompilerRunner( cacheVersions: List, reporter: ICReporter, private val usePreciseJavaTracking: Boolean, - private val buildHistoryFile: File, + buildHistoryFile: File, localStateDirs: Collection, private val modulesApiHistory: ModulesApiHistory ) : IncrementalCompilerRunner( @@ -112,7 +112,8 @@ class IncrementalJvmCompilerRunner( "caches-jvm", cacheVersions, reporter, - localStateDirs = localStateDirs + localStateDirs = localStateDirs, + buildHistoryFile = buildHistoryFile ) { override fun isICEnabled(): Boolean = IncrementalCompilation.isEnabledForJvm() @@ -310,22 +311,6 @@ class IncrementalJvmCompilerRunner( override fun additionalDirtyLookupSymbols(): Iterable = javaFilesProcessor?.allChangedSymbols ?: emptyList() - override fun processChangesAfterBuild( - compilationMode: CompilationMode, - currentBuildInfo: BuildInfo, - dirtyData: DirtyData - ) { - val prevDiffs = BuildDiffsStorage.readFromFile(buildHistoryFile, reporter)?.buildDiffs ?: emptyList() - val newDiff = if (compilationMode is CompilationMode.Incremental) { - BuildDifference(currentBuildInfo.startTS, true, dirtyData) - } else { - val emptyDirtyData = DirtyData() - BuildDifference(currentBuildInfo.startTS, false, emptyDirtyData) - } - - BuildDiffsStorage.writeToFile(buildHistoryFile, BuildDiffsStorage(prevDiffs + newDiff), reporter) - } - override fun makeServices( args: K2JVMCompilerArguments, lookupTracker: LookupTracker, @@ -387,57 +372,3 @@ var K2JVMCompilerArguments.destinationAsFile: File var K2JVMCompilerArguments.classpathAsList: List get() = classpath.orEmpty().split(File.pathSeparator).map(::File) set(value) { classpath = value.joinToString(separator = File.pathSeparator, transform = { it.path }) } - -private fun getClasspathChanges( - classpath: List, - changedFiles: ChangedFiles.Known, - lastBuildInfo: BuildInfo, - modulesApiHistory: ModulesApiHistory, - reporter: ICReporter? -): ChangesEither { - val classpathSet = HashSet() - for (file in classpath) { - when { - file.isFile -> classpathSet.add(file) - file.isDirectory -> file.walk().filterTo(classpathSet) { it.isFile } - } - } - - val modifiedClasspath = changedFiles.modified.filterTo(HashSet()) { it in classpathSet } - val removedClasspath = changedFiles.removed.filterTo(HashSet()) { it in classpathSet } - - // todo: removed classes could be processed normally - if (removedClasspath.isNotEmpty()) return ChangesEither.Unknown("Some files are removed from classpath $removedClasspath") - - if (modifiedClasspath.isEmpty()) return ChangesEither.Known() - - val lastBuildTS = lastBuildInfo.startTS - - val symbols = HashSet() - val fqNames = HashSet() - - val historyFilesEither = modulesApiHistory.historyFilesForChangedFiles(modifiedClasspath) - val historyFiles = when (historyFilesEither) { - is Either.Success> -> historyFilesEither.value - is Either.Error -> return ChangesEither.Unknown(historyFilesEither.reason) - } - - for (historyFile in historyFiles) { - val allBuilds = BuildDiffsStorage.readDiffsFromFile(historyFile, reporter = reporter) - ?: return ChangesEither.Unknown("Could not read diffs from $historyFile") - val (knownBuilds, newBuilds) = allBuilds.partition { it.ts <= lastBuildTS } - if (knownBuilds.isEmpty()) { - return ChangesEither.Unknown("No previously known builds for $historyFile") - } - - for (buildDiff in newBuilds) { - if (!buildDiff.isIncremental) return ChangesEither.Unknown("Non-incremental build from dependency $historyFile") - - val dirtyData = buildDiff.dirtyData - symbols.addAll(dirtyData.dirtyLookupSymbols) - fqNames.addAll(dirtyData.dirtyClassesFqNames) - } - } - - return ChangesEither.Known(symbols, fqNames) -} \ No newline at end of file diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/changesDetectionUtils.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/changesDetectionUtils.kt new file mode 100644 index 00000000000..f4a16fd6e20 --- /dev/null +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/changesDetectionUtils.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.incremental + +import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistory +import org.jetbrains.kotlin.incremental.util.Either +import org.jetbrains.kotlin.name.FqName +import java.io.File + +internal fun getClasspathChanges( + classpath: List, + changedFiles: ChangedFiles.Known, + lastBuildInfo: BuildInfo, + modulesApiHistory: ModulesApiHistory, + reporter: ICReporter? +): ChangesEither { + val classpathSet = HashSet() + for (file in classpath) { + when { + file.isFile -> classpathSet.add(file) + file.isDirectory -> file.walk().filterTo(classpathSet) { it.isFile } + } + } + + val modifiedClasspath = changedFiles.modified.filterTo(HashSet()) { it in classpathSet } + val removedClasspath = changedFiles.removed.filterTo(HashSet()) { it in classpathSet } + + // todo: removed classes could be processed normally + if (removedClasspath.isNotEmpty()) return ChangesEither.Unknown("Some files are removed from classpath $removedClasspath") + + if (modifiedClasspath.isEmpty()) return ChangesEither.Known() + + val lastBuildTS = lastBuildInfo.startTS + + val symbols = HashSet() + val fqNames = HashSet() + + val historyFilesEither = modulesApiHistory.historyFilesForChangedFiles(modifiedClasspath) + val historyFiles = when (historyFilesEither) { + is Either.Success> -> historyFilesEither.value + is Either.Error -> return ChangesEither.Unknown(historyFilesEither.reason) + } + + for (historyFile in historyFiles) { + val allBuilds = BuildDiffsStorage.readDiffsFromFile(historyFile, reporter = reporter) + ?: return ChangesEither.Unknown("Could not read diffs from $historyFile") + val (knownBuilds, newBuilds) = allBuilds.partition { it.ts <= lastBuildTS } + if (knownBuilds.isEmpty()) { + return ChangesEither.Unknown("No previously known builds for $historyFile") + } + + for (buildDiff in newBuilds) { + if (!buildDiff.isIncremental) return ChangesEither.Unknown("Non-incremental build from dependency $historyFile") + + val dirtyData = buildDiff.dirtyData + symbols.addAll(dirtyData.dirtyLookupSymbols) + fqNames.addAll(dirtyData.dirtyClassesFqNames) + } + } + + return ChangesEither.Known(symbols, fqNames) +} \ No newline at end of file diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/multiproject/ModulesApiHistory.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/multiproject/ModulesApiHistory.kt index ef7ca8a0326..e2d3a5cd8ca 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/multiproject/ModulesApiHistory.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/multiproject/ModulesApiHistory.kt @@ -22,7 +22,7 @@ object EmptyModulesApiHistory : ModulesApiHistory { Either.Error("Multi-module IC is not configured") } -open class ModulesApiHistoryJvm(protected val modulesInfo: IncrementalModuleInfo) : ModulesApiHistory { +abstract class ModulesApiHistoryBase(protected val modulesInfo: IncrementalModuleInfo) : ModulesApiHistory { protected val projectRootPath: Path = Paths.get(modulesInfo.projectRoot.absolutePath) private val dirToHistoryFileCache = HashMap>() @@ -86,7 +86,11 @@ open class ModulesApiHistoryJvm(protected val modulesInfo: IncrementalModuleInfo return Either.Success(history) } - protected open fun getBuildHistoryFilesForJar(jar: File): Either> { + protected abstract fun getBuildHistoryFilesForJar(jar: File): Either> +} + +class ModulesApiHistoryJvm(modulesInfo: IncrementalModuleInfo) : ModulesApiHistoryBase(modulesInfo) { + override fun getBuildHistoryFilesForJar(jar: File): Either> { val classListFile = modulesInfo.jarToClassListFile[jar] ?: return Either.Error("Unknown jar: $jar") if (!classListFile.isFile) return Either.Error("Class list file does not exist $classListFile") @@ -109,7 +113,18 @@ open class ModulesApiHistoryJvm(protected val modulesInfo: IncrementalModuleInfo } } -class ModulesApiHistoryAndroid(modulesInfo: IncrementalModuleInfo) : ModulesApiHistoryJvm(modulesInfo) { +class ModulesApiHistoryJs(modulesInfo: IncrementalModuleInfo) : ModulesApiHistoryBase(modulesInfo) { + override fun getBuildHistoryFilesForJar(jar: File): Either> { + val moduleEntry = modulesInfo.jarToModule[jar] + + return when { + moduleEntry != null -> Either.Success(setOf(moduleEntry.buildHistoryFile)) + else -> Either.Error("No module is found for jar $jar") + } + } +} + +class ModulesApiHistoryAndroid(modulesInfo: IncrementalModuleInfo) : ModulesApiHistoryBase(modulesInfo) { private val delegate = ModulesApiHistoryJvm(modulesInfo) override fun historyFilesForChangedFiles(changedFiles: Set): Either> { diff --git a/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/multiproject/ModulesApiHistoryAndroidTest.kt b/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/multiproject/ModulesApiHistoryAndroidTest.kt index 600b784510d..b85f28b21de 100644 --- a/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/multiproject/ModulesApiHistoryAndroidTest.kt +++ b/compiler/incremental-compilation-impl/test/org/jetbrains/kotlin/incremental/multiproject/ModulesApiHistoryAndroidTest.kt @@ -58,7 +58,8 @@ class ModulesApiHistoryAndroidTest { projectRoot = projectRoot, dirToModule = mapOf(appKotlinDestination to appEntry, libKotlinDestination to libEntry), nameToModules = mapOf("app" to setOf(appEntry), "lib" to setOf(libEntry)), - jarToClassListFile = mapOf() + jarToClassListFile = mapOf(), + jarToModule = mapOf() ) androidHistory = ModulesApiHistoryAndroid(info) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt index 5fde68151ec..3c0b110a1f7 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt @@ -529,7 +529,10 @@ abstract class BaseGradleIT { } add("-Pkotlin_version=" + options.kotlinVersion) - options.incremental?.let { add("-Pkotlin.incremental=$it") } + options.incremental?.let { + add("-Pkotlin.incremental=$it") + add("-Pkotlin.incremental.js=$it") + } options.usePreciseJavaTracking?.let { add("-Pkotlin.incremental.usePreciseJavaTracking=$it") } options.androidGradlePluginVersion?.let { add("-Pandroid_tools_version=$it") } if (options.debug) { diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/IncrementalCompilationMultiProjectIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/IncrementalCompilationMultiProjectIT.kt index fb32fb1f096..835e1abfcf0 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/IncrementalCompilationMultiProjectIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/IncrementalCompilationMultiProjectIT.kt @@ -8,10 +8,35 @@ import org.junit.Assert import org.junit.Test import java.io.File -class IncrementalCompilationMultiProjectIT : BaseGradleIT() { - override fun defaultBuildOptions(): BuildOptions = - super.defaultBuildOptions().copy(withDaemon = true, incremental = true) +class IncrementalCompilationJsMultiProjectIT : BaseIncrementalCompilationMultiProjectIT() { + override fun defaultProject(): Project { + val project = Project("incrementalMultiproject") + project.setupWorkingDir() + for (subProject in arrayOf("app", "lib")) { + val subProjectDir = project.projectDir.resolve(subProject) + subProjectDir.resolve("src/main/java").deleteRecursively() + val buildGradle = subProjectDir.resolve("build.gradle") + val buildJsGradle = subProjectDir.resolve("build-js.gradle") + buildJsGradle.copyTo(buildGradle, overwrite = true) + buildJsGradle.delete() + } + + return project + } + + override val additionalLibDependencies: String = + "implementation \"org.jetbrains.kotlin:kotlin-test-js:${'$'}kotlin_version\"" +} + +class IncrementalCompilationJvmMultiProjectIT : BaseIncrementalCompilationMultiProjectIT() { + override val additionalLibDependencies: String = + "implementation \"org.jetbrains.kotlin:kotlin-stdlib:${'$'}kotlin_version\"" + + override fun defaultProject(): Project = + Project("incrementalMultiproject") + + // todo: do the same for js backend @Test fun testDuplicatedClass() { val project = Project("duplicatedClass") @@ -28,174 +53,12 @@ class IncrementalCompilationMultiProjectIT : BaseGradleIT() { } } - @Test - fun testMoveFunctionFromLib() { - val project = Project("incrementalMultiproject") - project.build("build") { - assertSuccessful() - } - - val barUseABKt = project.projectDir.getFileByName("barUseAB.kt") - val barInApp = File(project.projectDir, "app/src/main/java/bar").apply { mkdirs() } - barUseABKt.copyTo(File(barInApp, barUseABKt.name)) - barUseABKt.delete() - - project.build("build") { - assertSuccessful() - val affectedSources = project.projectDir.getFilesByNames("fooCallUseAB.kt", "barUseAB.kt") - val relativePaths = project.relativize(affectedSources) - assertCompiledKotlinSources(relativePaths, weakTesting = false) - } - } - - @Test - fun testAddNewMethodToLib() { - val project = Project("incrementalMultiproject") - project.build("build") { - assertSuccessful() - } - - val aKt = project.projectDir.getFileByName("A.kt") - aKt.writeText( - """ -package bar - -open class A { - fun a() {} - fun newA() {} -} -""" - ) - - project.build("build") { - assertSuccessful() - val affectedSources = project.projectDir.getFilesByNames("A.kt", "B.kt", "AA.kt", "BB.kt") - val relativePaths = project.relativize(affectedSources) - assertCompiledKotlinSources(relativePaths, weakTesting = false) - } - } - - @Test - fun testLibClassBecameFinal() { - val project = Project("incrementalMultiproject") - project.build("build") { - assertSuccessful() - } - - val bKt = project.projectDir.getFileByName("B.kt") - bKt.modify { it.replace("open class", "class") } - - project.build("build") { - assertFailed() - val affectedSources = project.projectDir.getFilesByNames( - "B.kt", "barUseAB.kt", "barUseB.kt", - "BB.kt", "fooCallUseAB.kt", "fooUseB.kt" - ) - val relativePaths = project.relativize(affectedSources) - assertCompiledKotlinSources(relativePaths, weakTesting = false) - } - } - - @Test - fun testCleanBuildLib() { - val project = Project("incrementalMultiproject") - - project.build("build") { - assertSuccessful() - } - - project.build(":lib:clean") { - assertSuccessful() - } - - // Change file so Gradle won't skip :app:compile - project.projectFile("BarDummy.kt").modify { - it.replace("class BarDummy", "open class BarDummy") - } - project.build("build") { - assertSuccessful() - val affectedSources = project.projectDir.allKotlinFiles() - val relativePaths = project.relativize(affectedSources) - assertCompiledKotlinSources(relativePaths, weakTesting = false) - } - - val aaKt = project.projectFile("AA.kt") - aaKt.modify { "$it " } - project.build("build") { - assertSuccessful() - assertCompiledKotlinSources(project.relativize(aaKt), weakTesting = false) - } - } - - @Test - fun testAddDependencyToLib() { - val project = Project("incrementalMultiproject") - - project.build("build") { - assertSuccessful() - } - - val libBuildGradle = File(project.projectDir, "lib/build.gradle") - Assert.assertTrue("$libBuildGradle does not exist", libBuildGradle.exists()) - libBuildGradle.modify { - """ - $it - - dependencies { - implementation 'junit:junit:4.12' - } - """.trimIndent() - } - // Change file so Gradle won't skip :app:compile - project.projectFile("BarDummy.kt").modify { - it.replace("class BarDummy", "open class BarDummy") - } - - project.build("build") { - assertSuccessful() - val affectedSources = project.projectDir.allKotlinFiles() - val relativePaths = project.relativize(affectedSources) - assertCompiledKotlinSources(relativePaths, weakTesting = false) - } - - val aaKt = project.projectFile("AA.kt") - aaKt.modify { "$it " } - project.build("build") { - assertSuccessful() - assertCompiledKotlinSources(project.relativize(aaKt), weakTesting = false) - } - } - - @Test - fun testCompileErrorInLib() { - val project = Project("incrementalMultiproject") - project.build("build") { - assertSuccessful() - } - - val bKt = project.projectDir.getFileByName("B.kt") - bKt.delete() - - project.build("build") { - assertFailed() - } - - project.projectDir.getFileByName("barUseB.kt").delete() - project.projectDir.getFileByName("barUseAB.kt").delete() - - project.build("build") { - assertFailed() - val affectedSources = project.projectDir.allKotlinFiles() - val relativePaths = project.relativize(affectedSources) - assertCompiledKotlinSources(relativePaths, weakTesting = false) - } - } // checks that multi-project ic is disabled when there is a task that outputs to javaDestination dir // that is not JavaCompile or KotlinCompile @Test fun testCompileLibWithGroovy() { - val project = Project("incrementalMultiproject") + val project = defaultProject() project.setupWorkingDir() val lib = File(project.projectDir, "lib") val libBuildGradle = File(lib, "build.gradle") @@ -234,3 +97,175 @@ open class A { } } +abstract class BaseIncrementalCompilationMultiProjectIT : BaseGradleIT() { + override fun defaultBuildOptions(): BuildOptions = + super.defaultBuildOptions().copy(withDaemon = true, incremental = true) + + protected abstract fun defaultProject(): Project + + @Test + fun testMoveFunctionFromLib() { + val project = defaultProject() + project.build("build") { + assertSuccessful() + } + + val barUseABKt = project.projectDir.getFileByName("barUseAB.kt") + val barInApp = File(project.projectDir, "app/src/main/kotlin/bar").apply { mkdirs() } + barUseABKt.copyTo(File(barInApp, barUseABKt.name)) + barUseABKt.delete() + + project.build("build") { + assertSuccessful() + val affectedSources = project.projectDir.getFilesByNames("fooCallUseAB.kt", "barUseAB.kt") + val relativePaths = project.relativize(affectedSources) + assertCompiledKotlinSources(relativePaths, weakTesting = false) + } + } + + @Test + fun testAddNewMethodToLib() { + val project = defaultProject() + project.build("build") { + assertSuccessful() + } + + val aKt = project.projectDir.getFileByName("A.kt") + aKt.writeText( + """ +package bar + +open class A { + fun a() {} + fun newA() {} +} +""" + ) + + project.build("build") { + assertSuccessful() + val affectedSources = project.projectDir.getFilesByNames("A.kt", "B.kt", "AA.kt", "BB.kt") + val relativePaths = project.relativize(affectedSources) + assertCompiledKotlinSources(relativePaths, weakTesting = false) + } + } + + @Test + fun testLibClassBecameFinal() { + val project = defaultProject() + project.build("build") { + assertSuccessful() + } + + val bKt = project.projectDir.getFileByName("B.kt") + bKt.modify { it.replace("open class", "class") } + + project.build("build") { + assertFailed() + val affectedSources = project.projectDir.getFilesByNames( + "B.kt", "barUseAB.kt", "barUseB.kt", + "BB.kt", "fooCallUseAB.kt", "fooUseB.kt" + ) + val relativePaths = project.relativize(affectedSources) + assertCompiledKotlinSources(relativePaths, weakTesting = false) + } + } + + @Test + fun testCleanBuildLib() { + val project = defaultProject() + + project.build("build") { + assertSuccessful() + } + + project.build(":lib:clean") { + assertSuccessful() + } + + // Change file so Gradle won't skip :app:compile + project.projectFile("BarDummy.kt").modify { + it.replace("class BarDummy", "open class BarDummy") + } + project.build("build") { + assertSuccessful() + val affectedSources = project.projectDir.allKotlinFiles() + val relativePaths = project.relativize(affectedSources) + assertCompiledKotlinSources(relativePaths, weakTesting = false) + } + + val aaKt = project.projectFile("AA.kt") + aaKt.modify { "$it " } + project.build("build") { + assertSuccessful() + assertCompiledKotlinSources(project.relativize(aaKt), weakTesting = false) + } + } + + protected abstract val additionalLibDependencies: String + + @Test + fun testAddDependencyToLib() { + val project = defaultProject() + + project.build("build") { + assertSuccessful() + } + + val libBuildGradle = File(project.projectDir, "lib/build.gradle") + Assert.assertTrue("$libBuildGradle does not exist", libBuildGradle.exists()) + libBuildGradle.modify { + """ + $it + + dependencies { + $additionalLibDependencies + } + """.trimIndent() + } + // Change file so Gradle won't skip :app:compile + project.projectFile("BarDummy.kt").modify { + it.replace("class BarDummy", "open class BarDummy") + } + + project.build("build") { + assertSuccessful() + val affectedSources = project.projectDir.allKotlinFiles() + val relativePaths = project.relativize(affectedSources) + assertCompiledKotlinSources(relativePaths, weakTesting = false) + } + + val aaKt = project.projectFile("AA.kt") + aaKt.modify { "$it " } + project.build("build") { + assertSuccessful() + assertCompiledKotlinSources(project.relativize(aaKt), weakTesting = false) + } + } + + @Test + fun testCompileErrorInLib() { + val project = defaultProject() + project.build("build") { + assertSuccessful() + } + + val bKt = project.projectDir.getFileByName("B.kt") + bKt.delete() + + project.build("build") { + assertFailed() + } + + project.projectDir.getFileByName("barUseB.kt").delete() + project.projectDir.getFileByName("barUseAB.kt").delete() + + project.build("build") { + assertFailed() + val affectedSources = project.projectDir.allKotlinFiles() + val relativePaths = project.relativize(affectedSources) + assertCompiledKotlinSources(relativePaths, weakTesting = false) + } + } +} + diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt index 1a7d07c99b5..f1216b53af5 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kotlin2JsGradlePluginIT.kt @@ -3,6 +3,7 @@ package org.jetbrains.kotlin.gradle import org.gradle.api.logging.LogLevel import org.jetbrains.kotlin.gradle.tasks.USING_EXPERIMENTAL_JS_INCREMENTAL_COMPILATION_MESSAGE import org.jetbrains.kotlin.gradle.util.getFileByName +import org.jetbrains.kotlin.gradle.util.getFilesByNames import org.jetbrains.kotlin.gradle.util.modify import org.junit.Test import java.io.File @@ -334,7 +335,8 @@ class Kotlin2JsGradlePluginIT : BaseGradleIT() { build("build") { assertSuccessful() assertContains(USING_EXPERIMENTAL_JS_INCREMENTAL_COMPILATION_MESSAGE) - assertCompiledKotlinSources(project.relativize(allKotlinFiles - projectFile("DummyInLibMain.kt"))) + val affectedFiles = project.projectDir.getFilesByNames("A.kt", "useAInLibMain.kt", "useAInAppMain.kt", "useAInAppTest.kt") + assertCompiledKotlinSources(project.relativize(affectedFiles)) } } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/build-js.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/build-js.gradle new file mode 100644 index 00000000000..90f002e1ce5 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/build-js.gradle @@ -0,0 +1,7 @@ +apply plugin: 'kotlin2js' + +dependencies { + compile project(':lib') + // do not remove until KT-25488 is fixed + compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version" +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/AA.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/kotlin/foo/AA.kt similarity index 100% rename from libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/AA.kt rename to libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/kotlin/foo/AA.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/kotlin/foo/AAA.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/kotlin/foo/AAA.kt new file mode 100644 index 00000000000..d11f178ffa2 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/kotlin/foo/AAA.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package foo + +import bar.* + +class AAA : A() { + fun aa() {} +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/BB.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/kotlin/foo/BB.kt similarity index 100% rename from libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/BB.kt rename to libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/kotlin/foo/BB.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/FooDummy.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/kotlin/foo/FooDummy.kt similarity index 100% rename from libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/FooDummy.kt rename to libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/kotlin/foo/FooDummy.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/fooCallUseAB.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/kotlin/foo/fooCallUseAB.kt similarity index 100% rename from libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/fooCallUseAB.kt rename to libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/kotlin/foo/fooCallUseAB.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/fooUseA.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/kotlin/foo/fooUseA.kt similarity index 100% rename from libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/fooUseA.kt rename to libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/kotlin/foo/fooUseA.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/fooUseAA.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/kotlin/foo/fooUseAA.kt similarity index 100% rename from libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/fooUseAA.kt rename to libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/kotlin/foo/fooUseAA.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/fooUseB.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/kotlin/foo/fooUseB.kt similarity index 100% rename from libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/fooUseB.kt rename to libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/kotlin/foo/fooUseB.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/fooUseBB.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/kotlin/foo/fooUseBB.kt similarity index 100% rename from libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/java/foo/fooUseBB.kt rename to libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/app/src/main/kotlin/foo/fooUseBB.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/build-js.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/build-js.gradle new file mode 100644 index 00000000000..718db2a0c77 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/build-js.gradle @@ -0,0 +1,6 @@ +apply plugin: 'kotlin2js' + +dependencies { + // do not remove until KT-25488 is fixed + compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version" +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/A.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/kotlin/bar/A.kt similarity index 100% rename from libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/A.kt rename to libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/kotlin/bar/A.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/B.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/kotlin/bar/B.kt similarity index 100% rename from libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/B.kt rename to libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/kotlin/bar/B.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/BarDummy.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/kotlin/bar/BarDummy.kt similarity index 100% rename from libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/BarDummy.kt rename to libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/kotlin/bar/BarDummy.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/barUseA.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/kotlin/bar/barUseA.kt similarity index 100% rename from libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/barUseA.kt rename to libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/kotlin/bar/barUseA.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/barUseAB.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/kotlin/bar/barUseAB.kt similarity index 70% rename from libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/barUseAB.kt rename to libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/kotlin/bar/barUseAB.kt index 66ef988f639..72b0a958a7f 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/barUseAB.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/kotlin/bar/barUseAB.kt @@ -1,5 +1,6 @@ package bar fun useAB(b: B) { + // todo b.a() b.b() } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/barUseB.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/kotlin/bar/barUseB.kt similarity index 100% rename from libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/java/bar/barUseB.kt rename to libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/incrementalMultiproject/lib/src/main/kotlin/bar/barUseB.kt diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt index 05a081d8c7f..1fd538b26c2 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt @@ -28,6 +28,8 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageRenderer import org.gradle.api.invocation.Gradle +import org.gradle.api.plugins.JavaPluginConvention +import org.gradle.jvm.tasks.Jar import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.daemon.client.CompileServiceSession import org.jetbrains.kotlin.daemon.common.* @@ -37,8 +39,9 @@ import org.jetbrains.kotlin.gradle.incremental.GRADLE_CACHE_VERSION import org.jetbrains.kotlin.gradle.incremental.GRADLE_CACHE_VERSION_FILE_NAME import org.jetbrains.kotlin.gradle.utils.relativeToRoot import org.jetbrains.kotlin.gradle.plugin.kotlinDebug +import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile import org.jetbrains.kotlin.gradle.tasks.InspectClassesForMultiModuleIC -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile import org.jetbrains.kotlin.gradle.utils.newTmpFile import org.jetbrains.kotlin.incremental.* import java.io.ByteArrayOutputStream @@ -358,15 +361,22 @@ internal class GradleCompilerRunner(private val project: Project) : KotlinCompil val dirToModule = HashMap() val nameToModules = HashMap>() val jarToClassListFile = HashMap() + val jarToModule = HashMap() for (project in gradle.rootProject.allprojects) { for (task in project.tasks) { when (task) { - is KotlinCompile -> { + is AbstractKotlinCompile<*> -> { val module = IncrementalModuleEntry(project.path, task.moduleName, project.buildDir, task.buildHistoryFile) dirToModule[task.destinationDir] = module task.javaOutputDir?.let { dirToModule[it] = module } nameToModules.getOrPut(module.name) { HashSet() }.add(module) + + if (task is Kotlin2JsCompile) { + jarForSourceSet(project, task.sourceSetName)?.let { + jarToModule[it] = module + } + } } is InspectClassesForMultiModuleIC -> { jarToClassListFile[File(task.archivePath)] = task.classesListFile @@ -375,11 +385,24 @@ internal class GradleCompilerRunner(private val project: Project) : KotlinCompil } } - return IncrementalModuleInfo(gradle.rootProject.projectDir, dirToModule, nameToModules, jarToClassListFile) - .also { - cachedGradle = WeakReference(gradle) - cachedModulesInfo = it - } + return IncrementalModuleInfo( + projectRoot = gradle.rootProject.projectDir, + dirToModule = dirToModule, + nameToModules = nameToModules, + jarToClassListFile = jarToClassListFile, + jarToModule = jarToModule + ).also { + cachedGradle = WeakReference(gradle) + cachedModulesInfo = it + } + } + + private fun jarForSourceSet(project: Project, sourceSetName: String): File? { + val javaConvention = project.convention.findPlugin(JavaPluginConvention::class.java) + ?: return null + val sourceSet = javaConvention.sourceSets.findByName(sourceSetName) ?: return null + val jarTask = project.tasks.findByName(sourceSet.jarTaskName) as? Jar + return jarTask?.archivePath } @Synchronized 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 43b123583e2..71e088a4f35 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 @@ -527,7 +527,9 @@ open class Kotlin2JsCompile() : AbstractKotlinCompile(), computedCompilerClasspath, if (hasFilesInTaskBuildDirectory()) changedFiles else ChangedFiles.Unknown(), taskBuildDirectory, - messageCollector, outputItemCollector, args, + messageCollector, + outputItemCollector, + args, multiModuleICSettings = multiModuleICSettings ) }