diff --git a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompilationOptions.kt b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompilationOptions.kt index 72438ef864e..9d952bec3a7 100644 --- a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompilationOptions.kt +++ b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompilationOptions.kt @@ -60,13 +60,13 @@ class IncrementalCompilationOptions( reportSeverity: Int, /** @See [CompilationResultCategory]] */ requestedCompilationResults: Array, - val resultDifferenceFile: File? = null, - val friendDifferenceFile: File? = null, val usePreciseJavaTracking: Boolean, /** * Directories that should be cleared when IC decides to rebuild */ - val localStateDirs: List + val localStateDirs: List, + val buildHistoryFile: File, + val modulesInfo: IncrementalModuleInfo ) : CompilationOptions(compilerMode, targetPlatform, reportCategories, reportSeverity, requestedCompilationResults) { companion object { const val serialVersionUID: Long = 0 @@ -81,8 +81,7 @@ class IncrementalCompilationOptions( "workingDir=$workingDir, " + "customCacheVersionFileName='$customCacheVersionFileName', " + "customCacheVersion=$customCacheVersion, " + - "resultDifferenceFile=$resultDifferenceFile, " + - "friendDifferenceFile=$friendDifferenceFile, " + + "buildHistoryFile=$buildHistoryFile, " + "usePreciseJavaTracking=$usePreciseJavaTracking" + "localStateDirs=$localStateDirs" + ")" diff --git a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/IncrementalCompilerServicesFacade.kt b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/IncrementalCompilerServicesFacade.kt index 02e8026fab0..82ec215334f 100644 --- a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/IncrementalCompilerServicesFacade.kt +++ b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/IncrementalCompilerServicesFacade.kt @@ -16,7 +16,6 @@ package org.jetbrains.kotlin.daemon.common -import java.io.File import java.rmi.RemoteException interface IncrementalCompilerServicesFacade : CompilerServicesFacadeBase { @@ -29,14 +28,4 @@ interface IncrementalCompilerServicesFacade : CompilerServicesFacadeBase { @Throws(RemoteException::class) fun revert() - - // ChangesRegistry - @Throws(RemoteException::class) - fun registerChanges(timestamp: Long, dirtyData: SimpleDirtyData) - - @Throws(RemoteException::class) - fun unknownChanges(timestamp: Long) - - @Throws(RemoteException::class) - fun getChanges(artifact: File, sinceTS: Long): Iterable? } \ No newline at end of file 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 new file mode 100644 index 00000000000..2410b8d8d81 --- /dev/null +++ b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/IncrementalModuleInfo.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2000-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.daemon.common + +import java.io.File +import java.io.Serializable + +data class IncrementalModuleEntry( + private val projectPath: String, + val name: String, + val buildDir: File, + val buildHistoryFile: File +) : Serializable { + companion object { + private const val serialVersionUID = 0L + } +} + +class IncrementalModuleInfo( + val projectRoot: File, + val dirToModule: Map, + val nameToModules: Map> +) : Serializable { + companion object { + private const val serialVersionUID = 0L + } +} \ No newline at end of file diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt index 643680fe6dd..96013541e1a 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt @@ -41,8 +41,6 @@ import org.jetbrains.kotlin.cli.metadata.K2MetadataCompiler import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.daemon.common.* import org.jetbrains.kotlin.daemon.incremental.RemoteAnnotationsFileUpdater -import org.jetbrains.kotlin.daemon.incremental.RemoteArtifactChangesProvider -import org.jetbrains.kotlin.daemon.incremental.RemoteChangesRegistry import org.jetbrains.kotlin.daemon.report.CompileServicesFacadeMessageCollector import org.jetbrains.kotlin.daemon.report.DaemonMessageReporter import org.jetbrains.kotlin.daemon.report.DaemonMessageReporterPrintStreamAdapter @@ -50,6 +48,8 @@ import org.jetbrains.kotlin.daemon.report.RemoteICReporter import org.jetbrains.kotlin.incremental.* import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.parsing.classesFqNames +import org.jetbrains.kotlin.incremental.multiproject.EmptyModulesApiHistory +import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistoryImpl import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents import org.jetbrains.kotlin.modules.Module import org.jetbrains.kotlin.progress.CompilationCanceledStatus @@ -517,9 +517,6 @@ class CompileServiceImpl( ChangedFiles.Unknown() } - val artifactChanges = RemoteArtifactChangesProvider(servicesFacade) - val changesRegistry = RemoteChangesRegistry(servicesFacade) - val workingDir = incrementalCompilationOptions.workingDir val versions = commonCacheVersions(workingDir) + customCacheVersion(incrementalCompilationOptions.customCacheVersion, @@ -527,13 +524,19 @@ class CompileServiceImpl( workingDir, enabled = true) - val compiler = IncrementalJvmCompilerRunner(workingDir, javaSourceRoots, versions, - reporter, annotationFileUpdater, - artifactChanges, changesRegistry, - buildHistoryFile = incrementalCompilationOptions.resultDifferenceFile, - friendBuildHistoryFile = incrementalCompilationOptions.friendDifferenceFile, - usePreciseJavaTracking = incrementalCompilationOptions.usePreciseJavaTracking, - localStateDirs = incrementalCompilationOptions.localStateDirs + val modulesApiHistory = incrementalCompilationOptions.run { + ModulesApiHistoryImpl(modulesInfo) + } + + val compiler = IncrementalJvmCompilerRunner( + workingDir, + javaSourceRoots, + versions, + reporter, annotationFileUpdater, + buildHistoryFile = incrementalCompilationOptions.buildHistoryFile, + localStateDirs = incrementalCompilationOptions.localStateDirs, + usePreciseJavaTracking = incrementalCompilationOptions.usePreciseJavaTracking, + modulesApiHistory = modulesApiHistory ) return compiler.compile(allKotlinFiles, k2jvmArgs, compilerMessageCollector, changedFiles) } diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/incremental/RemoteArtifactChangesProvider.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/incremental/RemoteArtifactChangesProvider.kt deleted file mode 100644 index 505abf43c90..00000000000 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/incremental/RemoteArtifactChangesProvider.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.daemon.incremental - -import org.jetbrains.kotlin.daemon.common.IncrementalCompilerServicesFacade -import org.jetbrains.kotlin.incremental.DirtyData -import org.jetbrains.kotlin.incremental.multiproject.ArtifactChangesProvider -import java.io.File - -class RemoteArtifactChangesProvider(private val servicesFacade: IncrementalCompilerServicesFacade) : ArtifactChangesProvider { - override fun getChanges(artifact: File, sinceTS: Long): Iterable? = - servicesFacade.getChanges(artifact, sinceTS)?.map { it.toDirtyData() } -} diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/incremental/RemoteChangesRegistry.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/incremental/RemoteChangesRegistry.kt deleted file mode 100644 index c66a04dd585..00000000000 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/incremental/RemoteChangesRegistry.kt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.daemon.incremental - -import org.jetbrains.kotlin.daemon.common.IncrementalCompilerServicesFacade -import org.jetbrains.kotlin.incremental.DirtyData -import org.jetbrains.kotlin.incremental.multiproject.ChangesRegistry - -internal class RemoteChangesRegistry(private val servicesFacade: IncrementalCompilerServicesFacade) : ChangesRegistry { - override fun unknownChanges(timestamp: Long) { - servicesFacade.unknownChanges(timestamp) - } - - override fun registerChanges(timestamp: Long, dirtyData: DirtyData) { - servicesFacade.registerChanges(timestamp, dirtyData.toSimpleDirtyData()) - } -} \ No newline at end of file diff --git a/compiler/incremental-compilation-impl/build.gradle.kts b/compiler/incremental-compilation-impl/build.gradle.kts index bba109b2ae8..b1db241ecca 100644 --- a/compiler/incremental-compilation-impl/build.gradle.kts +++ b/compiler/incremental-compilation-impl/build.gradle.kts @@ -15,6 +15,7 @@ dependencies { compile(project(":compiler:frontend.java")) compile(project(":compiler:cli")) compile(project(":kotlin-build-common")) + compile(project(":compiler:daemon-common")) compileOnly(intellijCoreDep()) { includeJars("intellij-core") } compileOnly(intellijDep()) { includeJars("annotations") } diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/BuildDiffsStorage.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/BuildDiffsStorage.kt index 1ba8074d4b1..58a3248ec4d 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/BuildDiffsStorage.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/BuildDiffsStorage.kt @@ -29,6 +29,11 @@ data class BuildDifference(val ts: Long, val isIncremental: Boolean, val dirtyDa data class BuildDiffsStorage(val buildDiffs: List) { companion object { fun readFromFile(file: File, reporter: ICReporter?): BuildDiffsStorage? { + val diffs = readDiffsFromFile(file, reporter) + return diffs?.let { BuildDiffsStorage(it) } + } + + fun readDiffsFromFile(file: File, reporter: ICReporter?): MutableList? { fun reportFail(reason: String) { reporter?.report { "Could not read diff from file $file: $reason" } } @@ -48,7 +53,7 @@ data class BuildDiffsStorage(val buildDiffs: List) { repeat(size) { result.add(input.readBuildDifference()) } - return BuildDiffsStorage(result) + return result } } catch (e: IOException) { diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/ChangesEither.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/ChangesEither.kt index 4578827e1af..86d3227fdc8 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/ChangesEither.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/ChangesEither.kt @@ -23,5 +23,5 @@ internal sealed class ChangesEither { val lookupSymbols: Collection = emptyList(), val fqNames: Collection = emptyList() ) : ChangesEither() - internal class Unknown : ChangesEither() + internal class Unknown(val reason: String? = null) : ChangesEither() } \ No newline at end of file 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 1d87fa6ae2a..691cf1f2ecd 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 @@ -27,8 +27,6 @@ import org.jetbrains.kotlin.compilerRunner.toGeneratedFile 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.multiproject.ArtifactChangesProvider -import org.jetbrains.kotlin.incremental.multiproject.ChangesRegistry import org.jetbrains.kotlin.incremental.parsing.classesFqNames import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.progress.CompilationCanceledStatus @@ -43,8 +41,6 @@ abstract class IncrementalCompilerRunner< cacheDirName: String, protected val cacheVersions: List, protected val reporter: ICReporter, - protected val artifactChangesProvider: ArtifactChangesProvider?, - protected val changesRegistry: ChangesRegistry?, private val localStateDirs: Collection = emptyList() ) { @@ -307,16 +303,11 @@ abstract class IncrementalCompilerRunner< open fun runWithNoDirtyKotlinSources(caches: CacheManager): Boolean = false - protected open fun processChangesAfterBuild(compilationMode: CompilationMode, currentBuildInfo: BuildInfo, dirtyData: DirtyData) { - if (changesRegistry == null) return - - if (compilationMode is CompilationMode.Incremental) { - changesRegistry.registerChanges(currentBuildInfo.startTS, dirtyData) - } - else { - assert(compilationMode is CompilationMode.Rebuild) { "Unexpected compilation mode: ${compilationMode::class.java}" } - changesRegistry.unknownChanges(currentBuildInfo.startTS) - } + protected open fun processChangesAfterBuild( + compilationMode: CompilationMode, + currentBuildInfo: BuildInfo, + dirtyData: DirtyData + ) { } 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 9dc5e9bb28f..673f1942d94 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 @@ -67,9 +67,7 @@ class IncrementalJsCompilerRunner( workingDir, "caches-js", cacheVersions, - reporter, - artifactChangesProvider = null, - changesRegistry = null + reporter ) { override fun isICEnabled(): Boolean = IncrementalCompilation.isEnabled() && IncrementalCompilation.isEnabledForJs() 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 e62d878b761..f90f5bfb438 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 @@ -18,7 +18,6 @@ package org.jetbrains.kotlin.incremental import com.intellij.lang.java.JavaLanguage import com.intellij.openapi.util.Disposer -import com.intellij.openapi.util.io.FileUtil import com.intellij.psi.PsiClass import com.intellij.psi.PsiFile import com.intellij.psi.PsiFileFactory @@ -39,8 +38,9 @@ import org.jetbrains.kotlin.config.IncrementalCompilation 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.multiproject.ArtifactChangesProvider -import org.jetbrains.kotlin.incremental.multiproject.ChangesRegistry +import org.jetbrains.kotlin.incremental.multiproject.EmptyModulesApiHistory +import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistory +import org.jetbrains.kotlin.incremental.util.Either import org.jetbrains.kotlin.load.java.JavaClassesTracker import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents @@ -64,6 +64,7 @@ fun makeIncrementally( val rootsWalk = sourceRoots.asSequence().flatMap { it.walk() } val files = rootsWalk.filter(File::isFile) val sourceFiles = files.filter { it.extension.toLowerCase() in allExtensions }.toList() + val buildHistoryFile = File(cachesDir, "build-history.bin") withIC { val compiler = IncrementalJvmCompilerRunner( @@ -72,7 +73,9 @@ fun makeIncrementally( versions, reporter, // Use precise setting in case of non-Gradle build usePreciseJavaTracking = true, - localStateDirs = emptyList() + localStateDirs = emptyList(), + buildHistoryFile = buildHistoryFile, + modulesApiHistory = EmptyModulesApiHistory ) compiler.compile(sourceFiles, args, messageCollector, providedChangedFiles = null) } @@ -101,19 +104,15 @@ class IncrementalJvmCompilerRunner( cacheVersions: List, reporter: ICReporter, private var kaptAnnotationsFileUpdater: AnnotationFileUpdater? = null, - artifactChangesProvider: ArtifactChangesProvider? = null, - changesRegistry: ChangesRegistry? = null, - private val buildHistoryFile: File? = null, - private val friendBuildHistoryFile: File? = null, private val usePreciseJavaTracking: Boolean, - localStateDirs: Collection + private val buildHistoryFile: File, + localStateDirs: Collection, + private val modulesApiHistory: ModulesApiHistory ) : IncrementalCompilerRunner( workingDir, "caches-jvm", cacheVersions, reporter, - artifactChangesProvider, - changesRegistry, localStateDirs = localStateDirs ) { override fun isICEnabled(): Boolean = @@ -166,41 +165,18 @@ class IncrementalJvmCompilerRunner( val lastBuildInfo = BuildInfo.read(lastBuildInfoFile) ?: return CompilationMode.Rebuild { "No information on previous build" } reporter.report { "Last Kotlin Build info -- $lastBuildInfo" } - val changesFromFriend by lazy { - val myLastTS = lastBuildInfo.startTS - val storage = friendBuildHistoryFile?.let { BuildDiffsStorage.readFromFile(it, reporter) } ?: return@lazy ChangesEither.Unknown() + val classpathChanges = getClasspathChanges(args.classpathAsList, changedFiles, lastBuildInfo) - val (prevDiffs, newDiffs) = storage.buildDiffs.partition { it.ts < myLastTS } - if (prevDiffs.isEmpty()) return@lazy ChangesEither.Unknown() - - val dirtyLookupSymbols = HashSet() - val dirtyClassesFqNames = HashSet() - for ((_, isIncremental, dirtyData) in newDiffs) { - if (!isIncremental) return@lazy ChangesEither.Unknown() - - dirtyLookupSymbols.addAll(dirtyData.dirtyLookupSymbols) - dirtyClassesFqNames.addAll(dirtyData.dirtyClassesFqNames) + @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 -> { + markDirtyBy(classpathChanges.lookupSymbols) + markDirtyBy(classpathChanges.fqNames) } - - markDirtyBy(dirtyLookupSymbols) - markDirtyBy(dirtyClassesFqNames) - ChangesEither.Known(dirtyLookupSymbols, dirtyClassesFqNames) - } - val friendDirs = args.friendPaths?.map { File(it) } ?: emptyList() - for (file in changedFiles.removed.asSequence() + changedFiles.modified.asSequence()) { - if (!file.isClassFile()) continue - - val isFriendClassFile = friendDirs.any { FileUtil.isAncestor(it, file, false) } - if (isFriendClassFile && changesFromFriend is ChangesEither.Known) continue - - return CompilationMode.Rebuild { "Cannot get changes from modified or removed class file: ${reporter.pathsAsString(file)}" } - } - - val classpathSet = args.classpathAsList.toHashSet() - val modifiedClasspathEntries = changedFiles.modified.filter { it in classpathSet } - val classpathChanges = getClasspathChanges(modifiedClasspathEntries, lastBuildInfo) - if (classpathChanges !is ChangesEither.Known) { - return CompilationMode.Rebuild { "could not get changes from modified classpath entries: ${reporter.pathsAsString(modifiedClasspathEntries)}" } } if (!usePreciseJavaTracking) { @@ -221,8 +197,6 @@ class IncrementalJvmCompilerRunner( val removedClassesChanges = getRemovedClassesChanges(caches, changedFiles) markDirtyBy(androidLayoutChanges) - markDirtyBy(classpathChanges.lookupSymbols) - markDirtyBy(classpathChanges.fqNames) markDirtyBy(removedClassesChanges.dirtyLookupSymbols) markDirtyBy(removedClassesChanges.dirtyClassesFqNames) @@ -285,33 +259,49 @@ class IncrementalJvmCompilerRunner( } private fun getClasspathChanges( - modifiedClasspath: List, - lastBuildInfo: BuildInfo? + classpath: List, + changedFiles: ChangedFiles.Known, + lastBuildInfo: BuildInfo ): ChangesEither { - if (modifiedClasspath.isEmpty()) { - reporter.report {"No classpath changes"} - return ChangesEither.Known() + val classpathSet = HashSet() + for (file in classpath) { + when { + file.isFile -> classpathSet.add(file) + file.isDirectory -> file.walk().filterTo(classpathSet) { it.isFile } + } } - val lastBuildTS = lastBuildInfo?.startTS - if (lastBuildTS == null) { - reporter.report {"Could not determine last build timestamp"} - return ChangesEither.Unknown() - } + 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() - for (file in modifiedClasspath) { - val diffs = artifactChangesProvider?.getChanges(file, lastBuildTS) - if (diffs == null) { - reporter.report {"Could not get changes for file: $file"} - return ChangesEither.Unknown() + 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") } - diffs.forEach { - symbols.addAll(it.dirtyLookupSymbols) - fqNames.addAll(it.dirtyClassesFqNames) + for (buildDiff in newBuilds) { + val dirtyData = buildDiff.dirtyData + symbols.addAll(dirtyData.dirtyLookupSymbols) + fqNames.addAll(dirtyData.dirtyClassesFqNames) } } @@ -400,16 +390,15 @@ class IncrementalJvmCompilerRunner( override fun additionalDirtyLookupSymbols(): Iterable = javaFilesProcessor?.allChangedSymbols ?: emptyList() - override fun processChangesAfterBuild(compilationMode: CompilationMode, currentBuildInfo: BuildInfo, dirtyData: DirtyData) { - super.processChangesAfterBuild(compilationMode, currentBuildInfo, dirtyData) - - if (buildHistoryFile == null) return - + 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 { + } else { val emptyDirtyData = DirtyData() BuildDifference(currentBuildInfo.startTS, false, emptyDirtyData) } diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/multiproject/ArtifactChangesProvider.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/multiproject/ArtifactChangesProvider.kt deleted file mode 100644 index 81858007996..00000000000 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/multiproject/ArtifactChangesProvider.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.incremental.multiproject - -import org.jetbrains.kotlin.incremental.DirtyData -import java.io.File - -interface ArtifactChangesProvider { - fun getChanges(artifact: File, sinceTS: Long): Iterable? -} diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/multiproject/ChangesRegistry.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/multiproject/ChangesRegistry.kt deleted file mode 100644 index 866fb6d371e..00000000000 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/multiproject/ChangesRegistry.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.incremental.multiproject - -import org.jetbrains.kotlin.incremental.DirtyData - -interface ChangesRegistry { - fun registerChanges(timestamp: Long, dirtyData: DirtyData) - fun unknownChanges(timestamp: Long) -} \ 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 new file mode 100644 index 00000000000..36f8f08b14f --- /dev/null +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/multiproject/ModulesApiHistory.kt @@ -0,0 +1,86 @@ +/* + * Copyright 2000-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.multiproject + +import org.jetbrains.kotlin.daemon.common.IncrementalModuleInfo +import org.jetbrains.kotlin.incremental.util.Either +import java.io.File +import java.nio.file.Path +import java.nio.file.Paths +import java.util.zip.ZipFile + +interface ModulesApiHistory { + fun historyFilesForChangedFiles(changedFiles: Set): Either> +} + +object EmptyModulesApiHistory : ModulesApiHistory { + override fun historyFilesForChangedFiles(changedFiles: Set): Either> = + Either.Error("Multi-module IC is not configured") +} + +class ModulesApiHistoryImpl( + private val modulesInfo: IncrementalModuleInfo +) : ModulesApiHistory { + private val projectRootPath = Paths.get(modulesInfo.projectRoot.absolutePath) + private val dirToHistoryFileCache = HashMap() + + override fun historyFilesForChangedFiles(changedFiles: Set): Either> { + val result = HashSet() + val jarFiles = ArrayList() + val classFiles = ArrayList() + + for (file in changedFiles) { + val extension = file.extension + + when { + extension.equals("class", ignoreCase = true) -> { + classFiles.add(file) + } + extension.equals("jar", ignoreCase = true) -> { + jarFiles.add(file) + } + } + } + + for (jar in jarFiles) { + val historyEither = getBuildHistoryForJar(jar) + when (historyEither) { + is Either.Success -> result.add(historyEither.value) + is Either.Error -> return historyEither + } + } + + val classFileDirs = classFiles.groupBy { it.parentFile } + for ((dir, files) in classFileDirs) { + val buildHistory = getBuildHistoryForDir(dir) + ?: return Either.Error("Could not get build history for class files: ${files.joinToString()}") + result.add(buildHistory) + } + + return Either.Success(result) + } + + private fun getBuildHistoryForDir(file: File): File? = + dirToHistoryFileCache.getOrPut(file) { + val module = modulesInfo.dirToModule[file] + val parent = file.parentFile + + when { + module != null -> + module.buildHistoryFile + parent != null && projectRootPath.isParentOf(parent) -> + getBuildHistoryForDir(parent) + else -> + null + } + } + + private fun getBuildHistoryForJar(jar: File): Either = + Either.Error("Cannot get changes for jar $jar") + + private fun Path.isParentOf(path: Path) = path.startsWith(this) + private fun Path.isParentOf(file: File) = this.isParentOf(Paths.get(file.absolutePath)) +} \ No newline at end of file diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/util/Either.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/util/Either.kt new file mode 100644 index 00000000000..b142f6e3aa4 --- /dev/null +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/util/Either.kt @@ -0,0 +1,11 @@ +/* + * 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.util + +sealed class Either { + class Success(val value: T) : Either() + class Error(val reason: String) : Either() +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/agp25/kotlin/org/jetbrains/kotlin/gradle/plugin/android/Android25ProjectHandler.kt b/libraries/tools/kotlin-gradle-plugin/src/agp25/kotlin/org/jetbrains/kotlin/gradle/plugin/android/Android25ProjectHandler.kt index 8c285253e59..e17196f9e73 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/agp25/kotlin/org/jetbrains/kotlin/gradle/plugin/android/Android25ProjectHandler.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/agp25/kotlin/org/jetbrains/kotlin/gradle/plugin/android/Android25ProjectHandler.kt @@ -106,16 +106,6 @@ class Android25ProjectHandler(kotlinConfigurationTools: KotlinConfigurationTools override fun addJavaSourceDirectoryToVariantModel(variantData: BaseVariant, javaSourceDirectory: File) = variantData.addJavaSourceFoldersToModel(javaSourceDirectory) - override fun configureMultiProjectIc(project: Project, - variantData: BaseVariant, - javaTask: AbstractCompile, - kotlinTask: KotlinCompile, - kotlinAfterJavaTask: KotlinCompile?) { - //todo: No easy solution because of the absence of the output information in library modules - // Though it is affordable not to implement this for the first previews, because the impact is tolerable - // to some degree -- the dependent projects will rebuild non-incrementally when a library project changes - } - override fun getResDirectories(variantData: BaseVariant): List { return variantData.mergeResources?.computeResourceSetList0() ?: emptyList() } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleCompilerEnvironment.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleCompilerEnvironment.kt index 0007a3bf615..1fc188fb11e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleCompilerEnvironment.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleCompilerEnvironment.kt @@ -6,8 +6,6 @@ import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.gradle.tasks.GradleMessageCollector import org.jetbrains.kotlin.gradle.tasks.findToolsJar import org.jetbrains.kotlin.incremental.ChangedFiles -import org.jetbrains.kotlin.incremental.ICReporter -import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProvider import java.io.File import java.net.URL @@ -27,18 +25,14 @@ internal open class GradleCompilerEnvironment( } internal class GradleIncrementalCompilerEnvironment( - compilerClasspath: List, - val changedFiles: ChangedFiles, - val reporter: ICReporter, - val workingDir: File, - messageCollector: GradleMessageCollector, - outputItemsCollector: OutputItemsCollector, - compilerArgs: CommonCompilerArguments, - val kaptAnnotationsFileUpdater: AnnotationFileUpdater? = null, - val artifactDifferenceRegistryProvider: ArtifactDifferenceRegistryProvider? = null, - val artifactFile: File? = null, - val buildHistoryFile: File? = null, - val friendBuildHistoryFile: File? = null, - val usePreciseJavaTracking: Boolean = false, - val localStateDirs: List = emptyList() + compilerClasspath: List, + val changedFiles: ChangedFiles, + val workingDir: File, + messageCollector: GradleMessageCollector, + outputItemsCollector: OutputItemsCollector, + compilerArgs: CommonCompilerArguments, + val buildHistoryFile: File, + val kaptAnnotationsFileUpdater: AnnotationFileUpdater? = null, + val usePreciseJavaTracking: Boolean = false, + val localStateDirs: List = emptyList() ) : GradleCompilerEnvironment(compilerClasspath, messageCollector, outputItemsCollector, compilerArgs) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleIncrementalCompilerServicesFacadeImpl.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleIncrementalCompilerServicesFacadeImpl.kt index b90bda8b0e7..f83158dbe42 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleIncrementalCompilerServicesFacadeImpl.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleIncrementalCompilerServicesFacadeImpl.kt @@ -7,14 +7,8 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.daemon.client.reportFromDaemon import org.jetbrains.kotlin.daemon.common.* -import org.jetbrains.kotlin.daemon.incremental.toDirtyData -import org.jetbrains.kotlin.daemon.incremental.toSimpleDirtyData import org.jetbrains.kotlin.gradle.plugin.kotlinDebug -import org.jetbrains.kotlin.gradle.plugin.kotlinWarn -import org.jetbrains.kotlin.incremental.DirtyData -import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifference import org.jetbrains.kotlin.resolve.jvm.JvmClassName -import java.io.File import java.io.Serializable import java.rmi.Remote import java.rmi.server.UnicastRemoteObject @@ -67,32 +61,4 @@ internal class GradleIncrementalCompilerServicesFacadeImpl( override fun revert() { environment.kaptAnnotationsFileUpdater!!.revert() } - - override fun getChanges(artifact: File, sinceTS: Long): Iterable? { - val artifactChanges = environment.artifactDifferenceRegistryProvider?.withRegistry(environment.reporter) { registry -> - registry[artifact] - } ?: return null - - val (beforeLastBuild, afterLastBuild) = artifactChanges.partition { it.buildTS < sinceTS } - if (beforeLastBuild.isEmpty()) return null - - return afterLastBuild.map { it.dirtyData.toSimpleDirtyData() } - } - - override fun registerChanges(timestamp: Long, dirtyData: SimpleDirtyData) { - val artifactFile = environment.artifactFile ?: return - - environment.artifactDifferenceRegistryProvider?.withRegistry(environment.reporter) { registry -> - registry.add(artifactFile, ArtifactDifference(timestamp, dirtyData.toDirtyData())) - } - } - - override fun unknownChanges(timestamp: Long) { - val artifactFile = environment.artifactFile ?: return - - environment.artifactDifferenceRegistryProvider?.withRegistry(environment.reporter) { registry -> - registry.remove(artifactFile) - registry.add(artifactFile, ArtifactDifference(timestamp, DirtyData())) - } - } } 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 a28d8c8612b..c1f751af447 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,14 +28,19 @@ 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 com.intellij.openapi.util.io.FileUtil +import org.gradle.api.invocation.Gradle import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.daemon.client.CompileServiceSession import org.jetbrains.kotlin.daemon.common.* +import org.jetbrains.kotlin.daemon.common.IncrementalModuleEntry +import org.jetbrains.kotlin.daemon.common.IncrementalModuleInfo import org.jetbrains.kotlin.gradle.plugin.kotlinDebug +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.incremental.* import java.io.ByteArrayOutputStream import java.io.File import java.io.PrintStream +import java.lang.ref.WeakReference import java.net.URLClassLoader import java.rmi.RemoteException @@ -267,10 +272,10 @@ internal class GradleCompilerRunner(private val project: Project) : KotlinCompil requestedCompilationResults = arrayOf(CompilationResultCategory.IC_COMPILE_ITERATION.code), compilerMode = CompilerMode.INCREMENTAL_COMPILER, targetPlatform = targetPlatform, - resultDifferenceFile = environment.buildHistoryFile, - friendDifferenceFile = environment.friendBuildHistoryFile, usePreciseJavaTracking = environment.usePreciseJavaTracking, - localStateDirs = environment.localStateDirs + localStateDirs = environment.localStateDirs, + buildHistoryFile = environment.buildHistoryFile, + modulesInfo = buildModulesInfo(project.gradle) ) log.info("Options for KOTLIN DAEMON: $compilationOptions") @@ -340,6 +345,39 @@ internal class GradleCompilerRunner(private val project: Project) : KotlinCompil } companion object { + @Volatile + private var cachedGradle = WeakReference(null) + @Volatile + private var cachedModulesInfo: IncrementalModuleInfo? = null + + @Synchronized + private fun buildModulesInfo(gradle: Gradle): IncrementalModuleInfo { + if (cachedGradle.get() === gradle && cachedModulesInfo != null) return cachedModulesInfo!! + + val dirToModule = HashMap() + val nameToModules = HashMap>() + + for (project in gradle.rootProject.allprojects) { + for (task in project.tasks.withType(KotlinCompile::class.java)) { + val module = IncrementalModuleEntry(project.path, task.moduleName, project.buildDir, task.buildHistoryFile) + dirToModule[task.destinationDir] = module + nameToModules.getOrPut(module.name) { HashSet() }.add(module) + } + } + + return IncrementalModuleInfo(gradle.rootProject.projectDir, dirToModule, nameToModules) + .also { + cachedGradle = WeakReference(gradle) + cachedModulesInfo = it + } + } + + @Synchronized + internal fun clearBuildModulesInfo() { + cachedGradle = WeakReference(null) + cachedModulesInfo = null + } + // created once per gradle instance // when gradle daemon dies, kotlin daemon should die too // however kotlin daemon (if it idles enough) can die before gradle daemon dies diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinGradleBuildServices.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinGradleBuildServices.kt index bcc006d5186..7ad5067d994 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinGradleBuildServices.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinGradleBuildServices.kt @@ -27,17 +27,11 @@ import org.jetbrains.kotlin.compilerRunner.DELETED_SESSION_FILE_PREFIX import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile import org.jetbrains.kotlin.gradle.utils.isWindows -import org.jetbrains.kotlin.incremental.BuildCacheStorage -import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProvider import org.jetbrains.kotlin.incremental.relativeToRoot -import org.jetbrains.kotlin.incremental.stackTraceStr import org.jetbrains.kotlin.utils.addToStdlib.sumByLong -import java.io.File import java.lang.management.ManagementFactory - - -internal class KotlinGradleBuildServices private constructor(gradle: Gradle): BuildAdapter() { +internal class KotlinGradleBuildServices private constructor(gradle: Gradle) : BuildAdapter() { companion object { private val CLASS_NAME = KotlinGradleBuildServices::class.java.simpleName const val FORCE_SYSTEM_GC_MESSAGE = "Forcing System.gc()" @@ -72,13 +66,8 @@ internal class KotlinGradleBuildServices private constructor(gradle: Gradle): Bu private val log = Logging.getLogger(this.javaClass) private val cleanup = CompilerServicesCleanup() private var startMemory: Long? = null - internal val workingDir: File by lazy { File(gradle.rootProject.buildDir, "kotlin-build").apply { mkdirs() } } - private val buildCacheStorage: BuildCacheStorage by lazy { BuildCacheStorage(workingDir) } private val shouldReportMemoryUsage = System.getProperty(SHOULD_REPORT_MEMORY_USAGE_PROPERTY) != null - internal val artifactDifferenceRegistryProvider: ArtifactDifferenceRegistryProvider - get() = buildCacheStorage - // There is function with the same name in BuildAdapter, // but it is called before any plugin can attach build listener fun buildStarted() { @@ -99,6 +88,7 @@ internal class KotlinGradleBuildServices private constructor(gradle: Gradle): Bu else { log.kotlinDebug("Skipping kotlin cleanup since compiler wasn't called") } + GradleCompilerRunner.clearBuildModulesInfo() val rootProject = gradle.rootProject val sessionsDir = GradleCompilerRunner.sessionsDir(rootProject) @@ -125,45 +115,11 @@ internal class KotlinGradleBuildServices private constructor(gradle: Gradle): Bu log.lifecycle("[KOTLIN][PERF] Used memory after build: $endMem kb (difference since build start: ${"%+d".format(endMem - startMem)} kb)") } - closeArtifactDifferenceRegistry() gradle.removeListener(this) instance = null log.kotlinDebug(DISPOSE_MESSAGE) } - private fun closeArtifactDifferenceRegistry() { - var caughtError = false - try { - if (workingDir.exists()) { - // The working directory may have been removed by the clean task. - // https://youtrack.jetbrains.com/issue/KT-16298 - buildCacheStorage.flush(memoryCachesOnly = false) - } - } - catch (e: Throwable) { - log.kotlinDebug { "Error trying to flush artifact difference registry: ${e.stackTraceStr}" } - caughtError = true - } - finally { - try { - buildCacheStorage.close() - } - catch (e: Throwable) { - log.kotlinDebug { "Error trying to close artifact difference registry: ${e.stackTraceStr}" } - caughtError = true - } - } - - if (caughtError && workingDir.exists()) { - try { - workingDir.deleteRecursively() - } - catch (e: Throwable) { - log.kotlinDebug { "Error trying to delete kotlin-build $workingDir: ${e.stackTraceStr}" } - } - } - } - private fun getUsedMemoryKb(): Long? { if (!shouldReportMemoryUsage) return null diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt index ef4fa389b1c..11597630b52 100755 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt @@ -29,7 +29,6 @@ import org.jetbrains.kotlin.gradle.internal.* import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin.Companion.getKaptGeneratedClassesDir import org.jetbrains.kotlin.gradle.tasks.* import org.jetbrains.kotlin.gradle.utils.* -import org.jetbrains.kotlin.incremental.configureMultiProjectIncrementalCompilation import org.jetbrains.kotlin.scripting.gradle.ScriptingGradleSubplugin import java.io.File import java.net.URL @@ -129,8 +128,7 @@ internal class Kotlin2JvmSourceSetProcessor( sourceSet: SourceSet, tasksProvider: KotlinTasksProvider, kotlinSourceSetProvider: KotlinSourceSetProvider, - private val kotlinPluginVersion: String, - private val kotlinGradleBuildServices: KotlinGradleBuildServices + private val kotlinPluginVersion: String ) : KotlinSourceSetProcessor( project, javaBasePlugin, sourceSet, tasksProvider, kotlinSourceSetProvider, dslExtensionName = KOTLIN_DSL_NAME, @@ -189,11 +187,6 @@ internal class Kotlin2JvmSourceSetProcessor( syncOutputTask = createSyncOutputTask(project, kotlinTask, javaTask, kotlinAfterJavaTask, sourceSetName) } - val artifactFile = project.tryGetSingleArtifact() - configureMultiProjectIncrementalCompilation(project, kotlinTask, javaTask, kotlinAfterJavaTask, - kotlinGradleBuildServices.artifactDifferenceRegistryProvider, - artifactFile) - if (project.pluginManager.hasPlugin("java-library") && sourceSetName == SourceSet.MAIN_SOURCE_SET_NAME) { val (classesProviderTask, classesDirectory) = when { isSeparateClassesDirSupported -> (kotlinAfterJavaTask ?: kotlinTask).let { it to it.destinationDir } @@ -203,28 +196,10 @@ internal class Kotlin2JvmSourceSetProcessor( registerKotlinOutputForJavaLibrary(classesDirectory, classesProviderTask) } - // To make Gradle read this location from the task's @LocalState property and clean it on cache hit: - kotlinTask.buildServicesWorkingDir = Callable { kotlinGradleBuildServices.workingDir } } } } - private fun Project.tryGetSingleArtifact(): File? { - val log = logger - log.kotlinDebug { "Trying to determine single artifact for project $path" } - - val archives = configurations.findByName("archives") - if (archives == null) { - log.kotlinDebug { "Could not find 'archives' configuration for project $path" } - return null - } - - val artifacts = archives.artifacts.files.files - log.kotlinDebug { "All artifacts for project $path: [${artifacts.joinToString()}]" } - - return if (artifacts.size == 1) artifacts.first() else null - } - private fun registerKotlinOutputForJavaLibrary(outputDir: File, taskDependency: Task): Boolean { val configuration = project.configurations.getByName("apiElements") @@ -420,11 +395,10 @@ internal abstract class AbstractKotlinPlugin( internal open class KotlinPlugin( tasksProvider: KotlinTasksProvider, kotlinSourceSetProvider: KotlinSourceSetProvider, - kotlinPluginVersion: String, - private val kotlinGradleBuildServices: KotlinGradleBuildServices + kotlinPluginVersion: String ) : AbstractKotlinPlugin(tasksProvider, kotlinSourceSetProvider, kotlinPluginVersion) { override fun buildSourceSetProcessor(project: Project, javaBasePlugin: JavaBasePlugin, sourceSet: SourceSet, kotlinPluginVersion: String) = - Kotlin2JvmSourceSetProcessor(project, javaBasePlugin, sourceSet, tasksProvider, kotlinSourceSetProvider, kotlinPluginVersion, kotlinGradleBuildServices) + Kotlin2JvmSourceSetProcessor(project, javaBasePlugin, sourceSet, tasksProvider, kotlinSourceSetProvider, kotlinPluginVersion) override fun apply(project: Project) { project.createKaptExtension() @@ -454,8 +428,7 @@ internal open class Kotlin2JsPlugin( internal open class KotlinAndroidPlugin( val tasksProvider: KotlinTasksProvider, private val kotlinSourceSetProvider: KotlinSourceSetProvider, - private val kotlinPluginVersion: String, - private val kotlinGradleBuildServices: KotlinGradleBuildServices + private val kotlinPluginVersion: String ) : Plugin { override fun apply(project: Project) { @@ -470,8 +443,7 @@ internal open class KotlinAndroidPlugin( val kotlinTools = KotlinConfigurationTools( kotlinSourceSetProvider, tasksProvider, - kotlinPluginVersion, - kotlinGradleBuildServices) + kotlinPluginVersion) val legacyVersionThreshold = "2.5.0" @@ -492,17 +464,12 @@ internal open class KotlinAndroidPlugin( class KotlinConfigurationTools internal constructor(val kotlinSourceSetProvider: KotlinSourceSetProvider, val kotlinTasksProvider: KotlinTasksProvider, - val kotlinPluginVersion: String, - val kotlinGradleBuildServices: KotlinGradleBuildServices) + val kotlinPluginVersion: String) /** Part of Android configuration, that works only with the old public API. * @see [LegacyAndroidAndroidProjectHandler] that is implemented with the old internal API and [AndroidGradle25VariantProcessor] that works * with the new public API */ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTools: KotlinConfigurationTools) { - - protected val artifactDifferenceRegistryProvider get() = - kotlinConfigurationTools.kotlinGradleBuildServices.artifactDifferenceRegistryProvider - protected val logger = Logging.getLogger(this.javaClass) abstract fun forEachVariant(project: Project, action: (V) -> Unit): Unit @@ -525,12 +492,6 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationT kotlinTask: KotlinCompile, kotlinAfterJavaTask: KotlinCompile?): Unit - protected abstract fun configureMultiProjectIc(project: Project, - variantData: V, - javaTask: AbstractCompile, - kotlinTask: KotlinCompile, - kotlinAfterJavaTask: KotlinCompile?) - protected abstract fun wrapVariantDataForKapt(variantData: V): KaptVariantData fun handleProject(project: Project) { @@ -648,8 +609,6 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationT wireKotlinTasks(project, androidPlugin, androidExt, variantData, javaTask, kotlinTask, kotlinAfterJavaTask) - configureMultiProjectIc(project, variantData, javaTask, kotlinTask, kotlinAfterJavaTask) - val appliedPlugins = subpluginEnvironment.addSubpluginOptions( project, kotlinTask, javaTask, wrapVariantDataForKapt(variantData), this, null) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt index 043c099dd6b..22a325b94f6 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPluginWrapper.kt @@ -56,7 +56,7 @@ abstract class KotlinBasePluginWrapper(protected val fileResolver: FileResolver) open class KotlinPluginWrapper @Inject constructor(fileResolver: FileResolver): KotlinBasePluginWrapper(fileResolver) { override fun getPlugin(kotlinGradleBuildServices: KotlinGradleBuildServices) = - KotlinPlugin(KotlinTasksProvider(), KotlinSourceSetProviderImpl(fileResolver), kotlinPluginVersion, kotlinGradleBuildServices) + KotlinPlugin(KotlinTasksProvider(), KotlinSourceSetProviderImpl(fileResolver), kotlinPluginVersion) override val projectExtensionClass: KClass get() = KotlinJvmProjectExtension::class @@ -69,7 +69,7 @@ open class KotlinCommonPluginWrapper @Inject constructor(fileResolver: FileResol open class KotlinAndroidPluginWrapper @Inject constructor(fileResolver: FileResolver): KotlinBasePluginWrapper(fileResolver) { override fun getPlugin(kotlinGradleBuildServices: KotlinGradleBuildServices) = - KotlinAndroidPlugin(AndroidTasksProvider(), KotlinSourceSetProviderImpl(fileResolver), kotlinPluginVersion, kotlinGradleBuildServices) + KotlinAndroidPlugin(AndroidTasksProvider(), KotlinSourceSetProviderImpl(fileResolver), kotlinPluginVersion) } open class Kotlin2JsPluginWrapper @Inject constructor(fileResolver: FileResolver): KotlinBasePluginWrapper(fileResolver) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LegacyAndroidAndroidProjectHandler.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LegacyAndroidAndroidProjectHandler.kt index a045b7b5d6e..c00ab61674c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LegacyAndroidAndroidProjectHandler.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LegacyAndroidAndroidProjectHandler.kt @@ -16,8 +16,6 @@ import org.jetbrains.kotlin.gradle.internal.registerGeneratedJavaSource import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.utils.checkedReflection -import org.jetbrains.kotlin.incremental.configureMultiProjectIncrementalCompilation -import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProviderAndroidWrapper import java.io.File internal class LegacyAndroidAndroidProjectHandler(kotlinConfigurationTools: KotlinConfigurationTools) @@ -99,18 +97,6 @@ internal class LegacyAndroidAndroidProjectHandler(kotlinConfigurationTools: Kotl javaSourceDirectory: File) = variantData.addJavaSourceFoldersToModel(javaSourceDirectory) - override fun configureMultiProjectIc(project: Project, variantData: BaseVariantData, javaTask: AbstractCompile, kotlinTask: KotlinCompile, kotlinAfterJavaTask: KotlinCompile?) { - if ((kotlinAfterJavaTask ?: kotlinTask).incremental) { - val artifactFile = project.tryGetSingleArtifact(variantData) - val artifactDifferenceRegistryProvider = ArtifactDifferenceRegistryProviderAndroidWrapper( - artifactDifferenceRegistryProvider, - { AndroidGradleWrapper.getJarToAarMapping(variantData) } - ) - configureMultiProjectIncrementalCompilation(project, kotlinTask, javaTask, kotlinAfterJavaTask, - artifactDifferenceRegistryProvider, artifactFile) - } - } - override fun getTestedVariantData(variantData: BaseVariantData<*>): BaseVariantData<*>? = ((variantData as? TestVariantData)?.testedVariantData as? BaseVariantData<*>) @@ -118,19 +104,6 @@ internal class LegacyAndroidAndroidProjectHandler(kotlinConfigurationTools: Kotl return variantData.mergeResourcesTask?.rawInputFolders?.toList() ?: emptyList() } - private fun Project.tryGetSingleArtifact(variantData: BaseVariantData<*>): File? { - val log = logger - log.kotlinDebug { "Trying to determine single artifact for project $path" } - - val outputs = variantData.outputs - if (outputs.size != 1) { - log.kotlinDebug { "Output count != 1 for variant: ${outputs.map { it.outputFile.relativeTo(rootDir).path }.joinToString()}" } - return null - } - - return variantData.outputs.first().outputFile - } - private val BaseVariantData<*>.sourceProviders: List get() = variantConfiguration.sortedSourceProviders 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 41d67e9a542..aed3047dc80 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 @@ -41,12 +41,9 @@ import org.jetbrains.kotlin.gradle.internal.prepareCompilerArguments import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.utils.ParsedGradleVersion import org.jetbrains.kotlin.incremental.* -import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistry -import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProvider import org.jetbrains.kotlin.utils.LibraryUtils import java.io.File import java.util.* -import java.util.concurrent.Callable import kotlin.properties.Delegates const val ANNOTATIONS_PLUGIN_NAME = "org.jetbrains.kotlin.kapt" @@ -99,6 +96,9 @@ abstract class AbstractKotlinCompile() : AbstractKo logger.kotlinDebug { "Set $this.incremental=$value" } } + @get:Internal + internal val buildHistoryFile: File get() = File(taskBuildDirectory, "build-history.bin") + @get:Internal internal val pluginOptions = CompilerPluginOptions() @@ -267,9 +267,6 @@ open class KotlinCompile : AbstractKotlinCompile(), Kotl private var kaptAnnotationsFileUpdater: AnnotationFileUpdater? = null - @get:Internal - val buildHistoryFile: File get() = File(taskBuildDirectory, "build-history.bin") - @get:Internal val kaptOptions = KaptOptions() @@ -281,12 +278,6 @@ open class KotlinCompile : AbstractKotlinCompile(), Kotl @get:Optional var javaPackagePrefix: String? = null - @get:Internal - internal var artifactDifferenceRegistryProvider: ArtifactDifferenceRegistryProvider? = null - - @get:Internal - internal var artifactFile: File? = null - @get:Input var usePreciseJavaTracking: Boolean = true set(value) { @@ -294,9 +285,6 @@ open class KotlinCompile : AbstractKotlinCompile(), Kotl logger.kotlinDebug { "Set $this.usePreciseJavaTracking=$value" } } - @get:LocalState @get:Optional - internal var buildServicesWorkingDir: Callable? = null - init { incremental = true } @@ -350,23 +338,19 @@ open class KotlinCompile : AbstractKotlinCompile(), Kotl val messageCollector = GradleMessageCollector(logger) val outputItemCollector = OutputItemsCollectorImpl() val compilerRunner = GradleCompilerRunner(project) - val reporter = GradleICReporter(project.rootProject.projectDir) val environment = when { !incremental -> GradleCompilerEnvironment(computedCompilerClasspath, messageCollector, outputItemCollector, args) else -> { logger.info(USING_INCREMENTAL_COMPILATION_MESSAGE) - val friendTask = friendTaskName?.let { project.tasks.findByName(it) as? KotlinCompile } GradleIncrementalCompilerEnvironment( computedCompilerClasspath, if (hasFilesInTaskBuildDirectory()) changedFiles else ChangedFiles.Unknown(), - reporter, taskBuildDirectory, - messageCollector, outputItemCollector, args, kaptAnnotationsFileUpdater, - artifactDifferenceRegistryProvider, - artifactFile = artifactFile, + taskBuildDirectory, + messageCollector, outputItemCollector, args, buildHistoryFile = buildHistoryFile, - friendBuildHistoryFile = friendTask?.buildHistoryFile, + kaptAnnotationsFileUpdater = kaptAnnotationsFileUpdater, usePreciseJavaTracking = usePreciseJavaTracking, localStateDirs = outputDirectories ) @@ -386,18 +370,11 @@ open class KotlinCompile : AbstractKotlinCompile(), Kotl environment) processCompilerExitCode(exitCode) - artifactDifferenceRegistryProvider?.withRegistry(reporter) { - it.flush(true) - } } catch (e: Throwable) { cleanupOnError() - artifactDifferenceRegistryProvider?.clean() throw e } - finally { - artifactDifferenceRegistryProvider?.withRegistry(reporter, ArtifactDifferenceRegistry::close) - } anyClassesCompiled = true } @@ -525,8 +502,10 @@ open class Kotlin2JsCompile() : AbstractKotlinCompile(), GradleIncrementalCompilerEnvironment( computedCompilerClasspath, if (hasFilesInTaskBuildDirectory()) changedFiles else ChangedFiles.Unknown(), - reporter, taskBuildDirectory, - messageCollector, outputItemCollector, args) + taskBuildDirectory, + messageCollector, outputItemCollector, args, + buildHistoryFile = buildHistoryFile + ) } else -> { GradleCompilerEnvironment(computedCompilerClasspath, messageCollector, outputItemCollector, args) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/TasksProvider.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/TasksProvider.kt index 93d47370b87..a8f93717522 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/TasksProvider.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/TasksProvider.kt @@ -23,19 +23,19 @@ import org.jetbrains.kotlin.gradle.plugin.mapKotlinTaskProperties internal open class KotlinTasksProvider { fun createKotlinJVMTask(project: Project, name: String, sourceSetName: String): KotlinCompile = - project.tasks.create(name, KotlinCompile::class.java).apply { - configure(project, sourceSetName) - } + project.tasks.create(name, KotlinCompile::class.java).apply { + configure(project, sourceSetName) + } fun createKotlinJSTask(project: Project, name: String, sourceSetName: String): Kotlin2JsCompile = - project.tasks.create(name, Kotlin2JsCompile::class.java).apply { - configure(project, sourceSetName) - } + project.tasks.create(name, Kotlin2JsCompile::class.java).apply { + configure(project, sourceSetName) + } fun createKotlinCommonTask(project: Project, name: String, sourceSetName: String): KotlinCompileCommon = - project.tasks.create(name, KotlinCompileCommon::class.java).apply { - configure(project, sourceSetName) - } + project.tasks.create(name, KotlinCompileCommon::class.java).apply { + configure(project, sourceSetName) + } private fun AbstractKotlinCompile<*>.configure(project: Project, sourceSetName: String) { this.sourceSetName = sourceSetName @@ -44,20 +44,20 @@ internal open class KotlinTasksProvider { } protected open val taskToFriendTaskMapper: TaskToFriendTaskMapper = - RegexTaskToFriendTaskMapper.Default() + RegexTaskToFriendTaskMapper.Default() } internal class KotlinCommonTasksProvider : KotlinTasksProvider() { override val taskToFriendTaskMapper: TaskToFriendTaskMapper = - RegexTaskToFriendTaskMapper.Common() + RegexTaskToFriendTaskMapper.Common() } internal class Kotlin2JsTasksProvider : KotlinTasksProvider() { override val taskToFriendTaskMapper: TaskToFriendTaskMapper = - RegexTaskToFriendTaskMapper.JavaScript() + RegexTaskToFriendTaskMapper.JavaScript() } internal class AndroidTasksProvider : KotlinTasksProvider() { override val taskToFriendTaskMapper: TaskToFriendTaskMapper = - RegexTaskToFriendTaskMapper.Android() + RegexTaskToFriendTaskMapper.Android() } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/incremental/BuildCacheStorage.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/incremental/BuildCacheStorage.kt deleted file mode 100644 index a01d1857c9d..00000000000 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/incremental/BuildCacheStorage.kt +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.incremental - -import org.gradle.api.logging.Logging -import org.jetbrains.kotlin.gradle.plugin.kotlinDebug -import org.jetbrains.kotlin.incremental.CacheVersion -import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistry -import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryImpl -import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProvider -import org.jetbrains.kotlin.incremental.stackTraceStr -import org.jetbrains.kotlin.incremental.storage.BasicMapsOwner -import java.io.File - -/** - * "Global" cache holder. Should be created once per root project. - */ -internal class BuildCacheStorage(private val workingDir: File) : BasicMapsOwner(workingDir), ArtifactDifferenceRegistryProvider { - companion object { - private val OWN_VERSION = 0 - private val ARTIFACT_DIFFERENCE = "artifact-difference" - } - - private val log = Logging.getLogger(this.javaClass) - private val versionFile = File(workingDir, "version.txt") - private val version = CacheVersion( - OWN_VERSION, - versionFile, - whenVersionChanged = CacheVersion.Action.REBUILD_ALL_KOTLIN, - whenTurnedOff = CacheVersion.Action.REBUILD_ALL_KOTLIN, - whenTurnedOn = CacheVersion.Action.REBUILD_ALL_KOTLIN, - // assume it's always enabled for simplicity (if IC is not enabled, just don't write to cache) - isEnabled = { true }) - - @Volatile - private var artifactDifferenceRegistry: ArtifactDifferenceRegistryImpl? = null - - @Synchronized - override fun withRegistry(report: (String)->Unit, fn: (ArtifactDifferenceRegistry)->T): T? { - try { - if (artifactDifferenceRegistry == null) { - artifactDifferenceRegistry = registerMap(ArtifactDifferenceRegistryImpl(ARTIFACT_DIFFERENCE.storageFile)) - } - - return fn(artifactDifferenceRegistry!!) - } - catch (e1: Throwable) { - report("Error accessing artifact file difference registry: ${e1.stackTraceStr}}") - report("Cleaning artifact difference storage and trying again") - clean() - - try { - artifactDifferenceRegistry = registerMap(ArtifactDifferenceRegistryImpl(ARTIFACT_DIFFERENCE.storageFile)) - return fn(artifactDifferenceRegistry!!) - } - catch (e2: Throwable) { - report("Second error accessing artifact file difference registry: ${e2.stackTraceStr}}") - } - } - - return null - } - - init { - if (version.checkVersion() != CacheVersion.Action.DO_NOTHING) { - log.kotlinDebug { "Cache version is not up-to-date" } - clean() - } - } - - @Synchronized - override fun clean() { - try { - close() - } - catch (e: Throwable) { - log.kotlinDebug { "Exception while closing caches: ${e.stackTraceStr}" } - } - - workingDir.deleteRecursively() - workingDir.mkdirs() - versionFile.delete() - } - - override fun flush(memoryCachesOnly: Boolean) { - super.flush(memoryCachesOnly) - version.saveIfNeeded() - } - - override fun close() { - super.close() - artifactDifferenceRegistry = null - } -} diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/incremental/multiProjectIncrementalCompilationUtil.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/incremental/multiProjectIncrementalCompilationUtil.kt deleted file mode 100644 index b3ad90e061a..00000000000 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/incremental/multiProjectIncrementalCompilationUtil.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.incremental - -import org.gradle.api.Project -import org.gradle.api.Task -import org.gradle.api.logging.Logger -import org.gradle.api.tasks.compile.AbstractCompile -import org.gradle.api.tasks.compile.JavaCompile -import com.intellij.openapi.util.io.FileUtil -import org.jetbrains.kotlin.gradle.plugin.kotlinDebug -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile -import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProvider -import java.io.File - -internal fun configureMultiProjectIncrementalCompilation( - project: Project, - kotlinTask: KotlinCompile, - javaTask: AbstractCompile, - kotlinAfterJavaTask: KotlinCompile?, - artifactDifferenceRegistryProvider: ArtifactDifferenceRegistryProvider, - artifactFile: File? -) { - val log: Logger = kotlinTask.logger - log.kotlinDebug { "Configuring multi-project incremental compilation for project ${project.path}" } - - fun cannotPerformMultiProjectIC(reason: String) { - log.kotlinDebug { - "Multi-project kotlin incremental compilation won't be performed for projects that depend on ${project.path}: $reason" - } - if (artifactFile != null) { - artifactDifferenceRegistryProvider.withRegistry({log.kotlinDebug {it}}) { - it.remove(artifactFile) - } - } - } - - fun isUnknownTaskOutputtingToJavaDestination(task: Task): Boolean { - return task !is JavaCompile && - task !is KotlinCompile && - task is AbstractCompile && - FileUtil.isAncestor(javaTask.destinationDir, task.destinationDir, /* strict = */ false) - } - - if (!kotlinTask.incremental) { - return cannotPerformMultiProjectIC(reason = "incremental compilation is not enabled") - } - - // todo: split registry for reading and writing changes - val illegalTask = project.tasks.find(::isUnknownTaskOutputtingToJavaDestination) - if (illegalTask != null) { - return cannotPerformMultiProjectIC(reason = "unknown task outputs to java destination dir ${illegalTask.path} $(${illegalTask.javaClass})") - } - - val kotlinCompile = kotlinAfterJavaTask ?: kotlinTask - kotlinCompile.artifactDifferenceRegistryProvider = artifactDifferenceRegistryProvider - kotlinCompile.artifactFile = artifactFile -} diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/incremental/multiproject/ArtifactDifferenceRegistry.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/incremental/multiproject/ArtifactDifferenceRegistry.kt deleted file mode 100644 index df659804efb..00000000000 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/incremental/multiproject/ArtifactDifferenceRegistry.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.incremental.multiproject - -import org.jetbrains.kotlin.incremental.DirtyData -import org.jetbrains.kotlin.incremental.ICReporter -import java.io.File - -interface ArtifactDifferenceRegistry { - operator fun get(artifact: File): Iterable? - fun add(artifact: File, difference: ArtifactDifference) - fun remove(artifact: File) - fun flush(memoryCachesOnly: Boolean) - fun close() -} - -class ArtifactDifference(val buildTS: Long, val dirtyData: DirtyData) - -interface ArtifactDifferenceRegistryProvider { - fun withRegistry( - report: (String) -> Unit, - fn: (ArtifactDifferenceRegistry) -> T - ): T? - - fun withRegistry( - reporter: ICReporter, - fn: (ArtifactDifferenceRegistry) -> T - ): T? { - return withRegistry({reporter.report {it}}, fn) - } - - fun clean() -} diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/incremental/multiproject/ArtifactDifferenceRegistryAndroidWrapper.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/incremental/multiproject/ArtifactDifferenceRegistryAndroidWrapper.kt deleted file mode 100644 index 0cd969b6237..00000000000 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/incremental/multiproject/ArtifactDifferenceRegistryAndroidWrapper.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.incremental.multiproject - -import java.io.File - -internal class ArtifactDifferenceRegistryProviderAndroidWrapper( - private val provider: ArtifactDifferenceRegistryProvider, - private val jarToAarMapping: () -> Map -) : ArtifactDifferenceRegistryProvider { - override fun withRegistry(report: (String)->Unit, fn: (ArtifactDifferenceRegistry)->T): T? { - return provider.withRegistry(report) { originalRegistry -> - val wrapped = ArtifactDifferenceRegistryAndroidWrapper(originalRegistry, jarToAarMapping()) - fn(wrapped) - } - } - - override fun clean() { - provider.clean() - } -} - -// When lib is compiled, changes are associated with .aar files. -// However when app is compiled, there is just .jar in classpath. -private class ArtifactDifferenceRegistryAndroidWrapper( - private val registry: ArtifactDifferenceRegistry, - private val jarToAarMapping: Map -) : ArtifactDifferenceRegistry by registry { - override fun get(artifact: File): Iterable? { - val mappedFile = jarToAarMapping[artifact] ?: return null - return registry[mappedFile] - } -} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/incremental/multiproject/ArtifactDifferenceRegistryImpl.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/incremental/multiproject/ArtifactDifferenceRegistryImpl.kt deleted file mode 100644 index 00e46d4d9df..00000000000 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/incremental/multiproject/ArtifactDifferenceRegistryImpl.kt +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.incremental.multiproject - -import com.intellij.util.io.DataExternalizer -import org.jetbrains.kotlin.incremental.DirtyData -import org.jetbrains.kotlin.incremental.LookupSymbol -import org.jetbrains.kotlin.incremental.storage.BasicStringMap -import org.jetbrains.kotlin.name.FqName -import java.io.DataInput -import java.io.DataOutput -import java.io.File -import java.util.* - -internal class ArtifactDifferenceRegistryImpl( - storageFile: File -) : ArtifactDifferenceRegistry, BasicStringMap>( - storageFile, - ArtifactDifferenceCollectionExternalizer -) { - companion object { - private val MAX_BUILDS_PER_ARTIFACT = 10 - } - - override fun get(artifact: File): Iterable? = - storage[artifact.canonicalPath] - - override fun add(artifact: File, difference: ArtifactDifference) { - val key = artifact.canonicalPath - val oldVal = storage[key] ?: emptyList() - val newVal = ArrayList(oldVal) - newVal.add(difference) - newVal.sortBy { it.buildTS } - storage[key] = newVal.takeLast(MAX_BUILDS_PER_ARTIFACT) - } - - override fun remove(artifact: File) { - storage.remove(artifact.canonicalPath) - } - - override fun dumpValue(value: Collection): String = - value.sortedBy { it.buildTS }.joinToString(separator = ",\n\t") { diff -> - "{ " + - "timestamp: ${diff.buildTS}, " + - "lookup symbols: [${diff.dirtyData.dirtyLookupSymbols.dumpLookupSymbols()}], " + - "fq names: [${diff.dirtyData.dirtyClassesFqNames.dumpFqNames()}]" - "}" - } -} - -private fun Collection.takeLast(n: Int): Collection = - drop(Math.max(size - n, 0)) - -private fun Collection.dumpLookupSymbols(): String = - map { "${it.scope}#${it.name}" }.sorted().joinToString() - -private fun Collection.dumpFqNames(): String = - map(FqName::asString).sorted().joinToString() - -private object ArtifactDifferenceCollectionExternalizer : DataExternalizer> { - override fun read(input: DataInput): Collection = - input.readCollectionTo(ArrayList()) { - val buildTS = readLong() - val dirtyLookupSymbols = readCollectionTo(HashSet()) { - val scope = readUTF() - val name = readUTF() - LookupSymbol(name, scope) - } - val dirtyFqNames = readCollectionTo(HashSet()) { - FqName(readUTF()) - } - ArtifactDifference(buildTS, DirtyData(dirtyLookupSymbols, dirtyFqNames)) - } - - override fun save(output: DataOutput, value: Collection) { - output.writeCollection(value) { diff -> - writeLong(diff.buildTS) - writeCollection(diff.dirtyData.dirtyLookupSymbols) { - writeUTF(it.scope) - writeUTF(it.name) - } - writeCollection(diff.dirtyData.dirtyClassesFqNames) { - writeUTF(it.asString()) - } - } - } -} - -private inline fun DataInput.readCollectionTo(col: MutableCollection, readT: DataInput.() -> T): Collection { - val size = readInt() - - repeat(size) { - col.add(readT()) - } - - return col -} - -private inline fun DataOutput.writeCollection(col: Collection, writeT: DataOutput.(T) -> Unit) { - writeInt(col.size) - col.forEach { writeT(it) } -} \ No newline at end of file