From 0d1c803f71667ded0b313491d9e0c50511d63cbf Mon Sep 17 00:00:00 2001 From: Alexey Tsvetkov Date: Tue, 4 Oct 2016 00:20:33 +0300 Subject: [PATCH] Rebuild on cache corrupted exception #KT-14055 fixed --- .../plugin/KotlinGradleBuildServices.kt | 5 +- .../kotlin/gradle/plugin/KotlinPlugin.kt | 17 +++--- .../gradle/plugin/KotlinPluginWrapper.kt | 6 +- .../tasks/ArtifactDifferenceRegistry.kt | 20 ++++++- .../gradle/tasks/IncrementalCachesManager.kt | 6 +- .../jetbrains/kotlin/gradle/tasks/Tasks.kt | 58 +++++++++++++------ .../tasks/incremental/BuildCacheStorage.kt | 55 ++++++++++++++---- ...rtifactDifferenceRegistryAndroidWrapper.kt | 21 ++++++- .../multiProjectIncrementalCompilationUtil.kt | 14 +++-- .../gradle/tasks/incrementalCompilation.kt | 12 ++-- .../jetbrains/kotlin/incremental/jvmUtils.kt | 13 +++++ 11 files changed, 171 insertions(+), 56 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/incremental/jvmUtils.kt 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 f11bbaca343..42d71ca5b0e 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,6 +27,7 @@ import org.jetbrains.kotlin.com.intellij.openapi.vfs.impl.ZipHandler import org.jetbrains.kotlin.com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile import org.jetbrains.kotlin.gradle.tasks.ArtifactDifferenceRegistry +import org.jetbrains.kotlin.gradle.tasks.ArtifactDifferenceRegistryProvider import org.jetbrains.kotlin.gradle.tasks.incremental.BuildCacheStorage import java.io.File @@ -76,8 +77,8 @@ internal class KotlinGradleBuildServices private constructor(gradle: Gradle): Bu private val workingDir = File(gradle.rootProject.buildDir, "kotlin-build").apply { mkdirs() } private val buildCacheStorage = BuildCacheStorage(workingDir) - internal val artifactDifferenceRegistry: ArtifactDifferenceRegistry - get() = buildCacheStorage.artifactDifferenceRegistry + 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 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 62bdb2019d8..2d43e5db4fe 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 @@ -26,7 +26,7 @@ import org.jetbrains.kotlin.gradle.internal.Kapt2KotlinGradleSubplugin import org.jetbrains.kotlin.gradle.internal.initKapt import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper import org.jetbrains.kotlin.gradle.tasks.* -import org.jetbrains.kotlin.gradle.tasks.incremental.android.ArtifactDifferenceRegistryAndroidWrapper +import org.jetbrains.kotlin.gradle.tasks.incremental.android.ArtifactDifferenceRegistryProviderAndroidWrapper import org.jetbrains.kotlin.gradle.tasks.incremental.configureMultiProjectIncrementalCompilation import java.io.File import java.net.URL @@ -97,7 +97,7 @@ internal class Kotlin2JvmSourceSetProcessor( tasksProvider: KotlinTasksProvider, kotlinSourceSetProvider: KotlinSourceSetProvider, private val kotlinPluginVersion: String, - private val artifactDifferenceRegistry: ArtifactDifferenceRegistry + private val kotlinGradleBuildServices: KotlinGradleBuildServices ) : KotlinSourceSetProcessor( project, javaBasePlugin, sourceSet, tasksProvider, kotlinSourceSetProvider, dslExtensionName = KOTLIN_DSL_NAME, @@ -143,7 +143,8 @@ internal class Kotlin2JvmSourceSetProcessor( createSyncOutputTask(project, kotlinTask, javaTask, kotlinAfterJavaTask, sourceSetName) val artifactFile = project.tryGetSingleArtifact() configureMultiProjectIncrementalCompilation(project, kotlinTask, javaTask, kotlinAfterJavaTask, - artifactDifferenceRegistry, artifactFile) + kotlinGradleBuildServices.artifactDifferenceRegistryProvider, + artifactFile) } } } @@ -237,10 +238,10 @@ internal open class KotlinPlugin( tasksProvider: KotlinTasksProvider, kotlinSourceSetProvider: KotlinSourceSetProvider, kotlinPluginVersion: String, - private val artifactDifferenceRegistry: ArtifactDifferenceRegistry + private val kotlinGradleBuildServices: KotlinGradleBuildServices ) : AbstractKotlinPlugin(tasksProvider, kotlinSourceSetProvider, kotlinPluginVersion) { override fun buildSourceSetProcessor(project: Project, javaBasePlugin: JavaBasePlugin, sourceSet: SourceSet, kotlinPluginVersion: String) = - Kotlin2JvmSourceSetProcessor(project, javaBasePlugin, sourceSet, tasksProvider, kotlinSourceSetProvider, kotlinPluginVersion, artifactDifferenceRegistry) + Kotlin2JvmSourceSetProcessor(project, javaBasePlugin, sourceSet, tasksProvider, kotlinSourceSetProvider, kotlinPluginVersion, kotlinGradleBuildServices) override fun apply(project: Project) { project.createKaptExtension() @@ -262,7 +263,7 @@ internal open class KotlinAndroidPlugin( val tasksProvider: KotlinTasksProvider, private val kotlinSourceSetProvider: KotlinSourceSetProvider, private val kotlinPluginVersion: String, - private val artifactDifferenceRegistry: ArtifactDifferenceRegistry + private val kotlinGradleBuildServices: KotlinGradleBuildServices ) : Plugin { private val log = Logging.getLogger(this.javaClass) @@ -385,9 +386,9 @@ internal open class KotlinAndroidPlugin( if ((kotlinAfterJavaTask ?: kotlinTask).incremental) { val jarToAarMapping = AndroidGradleWrapper.getJarToAarMapping(variantData) val artifactFile = project.tryGetSingleArtifact(variantData) - val artifactDifferenceRegistryWrapper = ArtifactDifferenceRegistryAndroidWrapper(artifactDifferenceRegistry, jarToAarMapping) + val artifactDifferenceRegistryProvider = ArtifactDifferenceRegistryProviderAndroidWrapper(kotlinGradleBuildServices.artifactDifferenceRegistryProvider, jarToAarMapping) configureMultiProjectIncrementalCompilation(project, kotlinTask, javaTask, kotlinAfterJavaTask, - artifactDifferenceRegistryWrapper, artifactFile) + artifactDifferenceRegistryProvider, artifactFile) } } } 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 02754e77047..aeb6c2ff0c8 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 @@ -30,14 +30,12 @@ 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.artifactDifferenceRegistry) + KotlinPlugin(KotlinTasksProvider(), KotlinSourceSetProviderImpl(fileResolver), kotlinPluginVersion, kotlinGradleBuildServices) } open class KotlinAndroidPluginWrapper @Inject constructor(fileResolver: FileResolver): KotlinBasePluginWrapper(fileResolver) { override fun getPlugin(kotlinGradleBuildServices: KotlinGradleBuildServices) = - KotlinAndroidPlugin(AndroidTasksProvider(), KotlinSourceSetProviderImpl(fileResolver), kotlinPluginVersion, - kotlinGradleBuildServices.artifactDifferenceRegistry) + KotlinAndroidPlugin(AndroidTasksProvider(), KotlinSourceSetProviderImpl(fileResolver), kotlinPluginVersion, kotlinGradleBuildServices) } open class Kotlin2JsPluginWrapper @Inject constructor(fileResolver: FileResolver): KotlinBasePluginWrapper(fileResolver) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/ArtifactDifferenceRegistry.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/ArtifactDifferenceRegistry.kt index 02d0a14d619..19c1faf4939 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/ArtifactDifferenceRegistry.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/ArtifactDifferenceRegistry.kt @@ -1,12 +1,30 @@ package org.jetbrains.kotlin.gradle.tasks import org.jetbrains.kotlin.incremental.DirtyData +import org.jetbrains.kotlin.incremental.IncReporter import java.io.File internal interface ArtifactDifferenceRegistry { operator fun get(artifact: File): Iterable? fun add(artifact: File, difference: ArtifactDifference) fun remove(artifact: File) + fun flush(memoryCachesOnly: Boolean) } -internal class ArtifactDifference(val buildTS: Long, val dirtyData: DirtyData) \ No newline at end of file +internal class ArtifactDifference(val buildTS: Long, val dirtyData: DirtyData) + +internal interface ArtifactDifferenceRegistryProvider { + fun withRegistry( + report: (String) -> Unit, + fn: (ArtifactDifferenceRegistry) -> T + ): T? + + fun withRegistry( + reporter: IncReporter, + 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/gradle/tasks/IncrementalCachesManager.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/IncrementalCachesManager.kt index e2cddce5388..72acb9c0618 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/IncrementalCachesManager.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/IncrementalCachesManager.kt @@ -15,13 +15,15 @@ internal class IncrementalCachesManager ( private var lookupCacheOpen = false val incrementalCache: GradleIncrementalCacheImpl by lazy { + val cache = GradleIncrementalCacheImpl(targetDataRoot = incrementalCacheDir.apply { mkdirs() }, targetOutputDir = outputDir, target = targetId) incrementalCacheOpen = true - GradleIncrementalCacheImpl(targetDataRoot = incrementalCacheDir.apply { mkdirs() }, targetOutputDir = outputDir, target = targetId) + cache } val lookupCache: LookupStorage by lazy { + val cache = LookupStorage(lookupCacheDir.apply { mkdirs() }) lookupCacheOpen = true - LookupStorage(lookupCacheDir.apply { mkdirs() }) + cache } fun clean() { 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 c5a3fdf3076..2812a81373e 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 @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil import org.jetbrains.kotlin.cli.js.K2JSCompiler import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler import org.jetbrains.kotlin.com.intellij.openapi.util.io.FileUtil +import org.jetbrains.kotlin.com.intellij.util.io.PersistentEnumeratorBase import org.jetbrains.kotlin.compilerRunner.ArgumentUtils import org.jetbrains.kotlin.compilerRunner.OutputItemsCollector import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl @@ -31,7 +32,6 @@ import org.jetbrains.kotlin.gradle.dsl.* import org.jetbrains.kotlin.incremental.* import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.components.SourceRetentionAnnotationHandler -import org.jetbrains.kotlin.incremental.snapshots.FileCollectionDiff import org.jetbrains.kotlin.modules.TargetId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.progress.CompilationCanceledStatus @@ -134,7 +134,7 @@ open class KotlinCompile : AbstractKotlinCompile(), Kotl internal val kaptOptions = KaptOptions() internal val pluginOptions = CompilerPluginOptions() - internal var artifactDifferenceRegistry: ArtifactDifferenceRegistry? = null + internal var artifactDifferenceRegistryProvider: ArtifactDifferenceRegistryProvider? = null internal var artifactFile: File? = null // created only if kapt2 is active internal var sourceAnnotationsRegistry: SourceAnnotationsRegistry? = null @@ -177,30 +177,42 @@ open class KotlinCompile : AbstractKotlinCompile(), Kotl logger.warn(USING_EXPERIMENTAL_INCREMENTAL_MESSAGE) anyClassesCompiled = false - val javaFilesProcessor = ChangedJavaFilesProcessor() val targetId = TargetId(name = args.moduleName, type = "java-production") - val lookupTracker = LookupTrackerImpl(LookupTracker.DO_NOTHING) val lastBuildInfo = BuildInfo.read(lastBuildInfoFile) - val caches = IncrementalCachesManager(targetId, cacheDirectory, outputDir) val reporter = GradleIncReporter(project.rootProject.projectDir) + var caches = IncrementalCachesManager(targetId, cacheDirectory, outputDir) + reporter.report { "Last Kotlin Build info for task $path -- $lastBuildInfo" } - val compilationMode = calculateSourcesToCompile(javaFilesProcessor, - caches, - lastBuildInfo, - changedFiles, - classpath.toList(), - dirtySourcesSinceLastTimeFile, - artifactDifferenceRegistry, - reporter) - compileIncrementally(args, caches, javaFilesProcessor, lookupTracker, outputDir, allKotlinSources, targetId, compilationMode, reporter) + try { + val javaFilesProcessor = ChangedJavaFilesProcessor() + val compilationMode = calculateSourcesToCompile(javaFilesProcessor, + caches, + lastBuildInfo, + changedFiles, + classpath.toList(), + dirtySourcesSinceLastTimeFile, + artifactDifferenceRegistryProvider, + reporter) + compileIncrementally(args, caches, javaFilesProcessor, outputDir, allKotlinSources, targetId, compilationMode, reporter) + } + catch (e: PersistentEnumeratorBase.CorruptedException) { + caches.clean() + artifactDifferenceRegistryProvider?.clean() + + reporter.report { "Caches are corrupted. Rebuilding. $e" } + // try to rebuild + val javaFilesProcessor = ChangedJavaFilesProcessor() + caches = IncrementalCachesManager(targetId, cacheDirectory, outputDir) + val compilationMode = CompilationMode.Rebuild() + compileIncrementally(args, caches, javaFilesProcessor, outputDir, allKotlinSources, targetId, compilationMode, reporter) + } } private fun compileIncrementally( args: K2JVMCompilerArguments, caches: IncrementalCachesManager, javaFilesProcessor: ChangedJavaFilesProcessor, - lookupTracker: LookupTrackerImpl, outputDir: File, allKotlinSources: List, targetId: TargetId, @@ -234,6 +246,7 @@ open class KotlinCompile : AbstractKotlinCompile(), Kotl var exitCode = ExitCode.OK while (dirtySources.any()) { + val lookupTracker = LookupTrackerImpl(LookupTracker.DO_NOTHING) val outdatedClasses = caches.incrementalCache.classesBySources(dirtySources) caches.incrementalCache.markOutputClassesDirty(dirtySources) caches.incrementalCache.removeClassfilesBySources(dirtySources) @@ -269,7 +282,11 @@ open class KotlinCompile : AbstractKotlinCompile(), Kotl val generatedJavaFilesDiff = caches.incrementalCache.compareAndUpdateFileSnapshots(generatedJavaFiles) if (compilationMode is CompilationMode.Rebuild) { - artifactFile?.let { artifactDifferenceRegistry?.remove(it) } + artifactFile?.let { artifactFile -> + artifactDifferenceRegistryProvider?.withRegistry(reporter) { registry -> + registry.remove(artifactFile) + } + } break } @@ -304,10 +321,12 @@ open class KotlinCompile : AbstractKotlinCompile(), Kotl if (exitCode == ExitCode.OK && compilationMode is CompilationMode.Incremental) { buildDirtyLookupSymbols.addAll(javaFilesProcessor.allChangedSymbols) } - if (artifactFile != null && artifactDifferenceRegistry != null) { + if (artifactFile != null && artifactDifferenceRegistryProvider != null) { val dirtyData = DirtyData(buildDirtyLookupSymbols, buildDirtyFqNames) val artifactDifference = ArtifactDifference(currentBuildInfo.startTS, dirtyData) - artifactDifferenceRegistry!!.add(artifactFile!!, artifactDifference) + artifactDifferenceRegistryProvider!!.withRegistry(reporter) {registry -> + registry.add(artifactFile!!, artifactDifference) + } reporter.report { val dirtySymbolsSorted = buildDirtyLookupSymbols.map { it.scope + "#" + it.name }.sorted() "Added artifact difference for $artifactFile (ts: ${currentBuildInfo.startTS}): " + @@ -315,6 +334,9 @@ open class KotlinCompile : AbstractKotlinCompile(), Kotl } } + artifactDifferenceRegistryProvider?.withRegistry(reporter) { + it.flush(memoryCachesOnly = true) + } caches.close(flush = true) reporter.report { "flushed incremental caches" } processCompilerExitCode(exitCode) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/incremental/BuildCacheStorage.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/incremental/BuildCacheStorage.kt index 11e5766144b..4a6d6806e1e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/incremental/BuildCacheStorage.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/incremental/BuildCacheStorage.kt @@ -3,14 +3,16 @@ package org.jetbrains.kotlin.gradle.tasks.incremental import org.gradle.api.logging.Logging import org.jetbrains.kotlin.gradle.plugin.kotlinDebug import org.jetbrains.kotlin.gradle.tasks.ArtifactDifferenceRegistry +import org.jetbrains.kotlin.gradle.tasks.ArtifactDifferenceRegistryProvider import org.jetbrains.kotlin.incremental.CacheVersion +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(workingDir: File) : BasicMapsOwner() { +internal class BuildCacheStorage(workingDir: File) : BasicMapsOwner(), ArtifactDifferenceRegistryProvider { companion object { private val OWN_VERSION = 0 private val ARTIFACT_DIFFERENCE = "artifact-difference" @@ -28,23 +30,56 @@ internal class BuildCacheStorage(workingDir: File) : BasicMapsOwner() { // assume it's always enabled for simplicity (if IC is not enabled, just don't write to cache) isEnabled = { true }) - internal val artifactDifferenceRegistry: ArtifactDifferenceRegistry + @Volatile + private var artifactDifferenceRegistry: ArtifactDifferenceRegistryImpl? = null private val String.storageFile: File get() = File(cachesDir, this + "." + CACHE_EXTENSION) - init { - if (version.checkVersion() != CacheVersion.Action.DO_NOTHING) { - log.kotlinDebug { "Cache version is not up-to-date. Removing $cachesDir" } - cachesDir.deleteRecursively() - cachesDir.mkdirs() + @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}}") + } } - artifactDifferenceRegistry = registerMap(ArtifactDifferenceRegistryImpl(ARTIFACT_DIFFERENCE.storageFile)) + return null } + init { + if (version.checkVersion() != CacheVersion.Action.DO_NOTHING) { + log.kotlinDebug { "Cache version is not up-to-date" } + clean() + } + } + + @Synchronized override fun clean() { - super.clean() + try { + close() + } + catch (e: Throwable) { + log.kotlinDebug { "Exception while closing caches: ${e.stackTraceStr}" } + } + + cachesDir.deleteRecursively() + cachesDir.mkdirs() versionFile.delete() } @@ -52,4 +87,4 @@ internal class BuildCacheStorage(workingDir: File) : BasicMapsOwner() { super.close() version.saveIfNeeded() } -} \ No newline at end of file +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/incremental/android/ArtifactDifferenceRegistryAndroidWrapper.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/incremental/android/ArtifactDifferenceRegistryAndroidWrapper.kt index f015ac76e0e..cead9aac001 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/incremental/android/ArtifactDifferenceRegistryAndroidWrapper.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/incremental/android/ArtifactDifferenceRegistryAndroidWrapper.kt @@ -18,14 +18,31 @@ package org.jetbrains.kotlin.gradle.tasks.incremental.android import org.jetbrains.kotlin.gradle.tasks.ArtifactDifference import org.jetbrains.kotlin.gradle.tasks.ArtifactDifferenceRegistry +import org.jetbrains.kotlin.gradle.tasks.ArtifactDifferenceRegistryProvider 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. -internal class ArtifactDifferenceRegistryAndroidWrapper( +private class ArtifactDifferenceRegistryAndroidWrapper( private val registry: ArtifactDifferenceRegistry, private val jarToAarMapping: Map -): ArtifactDifferenceRegistry by registry { +) : ArtifactDifferenceRegistry by registry { override fun get(artifact: File): Iterable? { val mappedFile = jarToAarMapping[artifact] ?: return null return registry[mappedFile] diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/incremental/multiProjectIncrementalCompilationUtil.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/incremental/multiProjectIncrementalCompilationUtil.kt index fd0254453e8..b97a15d99f9 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/incremental/multiProjectIncrementalCompilationUtil.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/incremental/multiProjectIncrementalCompilationUtil.kt @@ -2,11 +2,13 @@ package org.jetbrains.kotlin.gradle.tasks.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 org.jetbrains.kotlin.com.intellij.openapi.util.io.FileUtil import org.jetbrains.kotlin.gradle.plugin.kotlinDebug import org.jetbrains.kotlin.gradle.tasks.ArtifactDifferenceRegistry +import org.jetbrains.kotlin.gradle.tasks.ArtifactDifferenceRegistryProvider import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import java.io.File @@ -15,17 +17,21 @@ internal fun configureMultiProjectIncrementalCompilation( kotlinTask: KotlinCompile, javaTask: AbstractCompile, kotlinAfterJavaTask: KotlinCompile?, - artifactDifferenceRegistry: ArtifactDifferenceRegistry, + artifactDifferenceRegistryProvider: ArtifactDifferenceRegistryProvider, artifactFile: File? ) { - val log = kotlinTask.logger + 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" } - artifactFile?.let { artifactDifferenceRegistry.remove(it) } + if (artifactFile != null) { + artifactDifferenceRegistryProvider.withRegistry({log.kotlinDebug {it}}) { + it.remove(artifactFile) + } + } } fun isUnknownTaskOutputtingToJavaDestination(task: Task): Boolean { @@ -46,6 +52,6 @@ internal fun configureMultiProjectIncrementalCompilation( } val kotlinCompile = kotlinAfterJavaTask ?: kotlinTask - kotlinCompile.artifactDifferenceRegistry = artifactDifferenceRegistry + kotlinCompile.artifactDifferenceRegistryProvider = artifactDifferenceRegistryProvider kotlinCompile.artifactFile = artifactFile } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/incrementalCompilation.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/incrementalCompilation.kt index 7553718bd89..0f5faa79016 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/incrementalCompilation.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/incrementalCompilation.kt @@ -18,7 +18,7 @@ internal fun calculateSourcesToCompile( changedFiles: ChangedFiles, classpath: Iterable, dirtySourcesSinceLastTimeFile: File, - artifactDifferenceRegistry: ArtifactDifferenceRegistry?, + artifactDifferenceRegistryProvider: ArtifactDifferenceRegistryProvider?, reporter: IncReporter ): CompilationMode { fun rebuild(reason: ()->String): CompilationMode { @@ -38,7 +38,7 @@ internal fun calculateSourcesToCompile( val classpathSet = classpath.toHashSet() val modifiedClasspathEntries = changedFiles.modified.filter { it in classpathSet } - val classpathChanges = getClasspathChanges(modifiedClasspathEntries, lastBuildInfo, artifactDifferenceRegistry, reporter) + val classpathChanges = getClasspathChanges(modifiedClasspathEntries, lastBuildInfo, artifactDifferenceRegistryProvider, reporter) if (classpathChanges is ChangesEither.Unknown) { return rebuild { "could not get changes from modified classpath entries: ${reporter.pathsAsString(modifiedClasspathEntries)}" } } @@ -89,14 +89,14 @@ internal fun calculateSourcesToCompile( private fun getClasspathChanges( modifiedClasspath: List, lastBuildInfo: BuildInfo?, - artifactDifferenceRegistry: ArtifactDifferenceRegistry?, + artifactDifferenceRegistryProvider: ArtifactDifferenceRegistryProvider?, reporter: IncReporter ): ChangesEither { if (modifiedClasspath.isEmpty()) { reporter.report { "No classpath changes" } return ChangesEither.Known() } - if (artifactDifferenceRegistry == null) { + if (artifactDifferenceRegistryProvider == null) { reporter.report { "No artifact history provider" } return ChangesEither.Unknown() } @@ -110,7 +110,9 @@ private fun getClasspathChanges( val symbols = HashSet() val fqNames = HashSet() for (file in modifiedClasspath) { - val diffs = artifactDifferenceRegistry[file] + val diffs = artifactDifferenceRegistryProvider.withRegistry(reporter) { artifactDifferenceRegistry -> + artifactDifferenceRegistry[file] + } if (diffs == null) { reporter.report { "Could not get changes for file: $file" } return ChangesEither.Unknown() diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/incremental/jvmUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/incremental/jvmUtils.kt new file mode 100644 index 00000000000..40a45fad75e --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/incremental/jvmUtils.kt @@ -0,0 +1,13 @@ +package org.jetbrains.kotlin.incremental + +import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream +import java.io.PrintStream + +internal val Throwable.stackTraceStr: String + get() { + val byteOutputStream = ByteOutputStream() + val printStream = PrintStream(byteOutputStream) + @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") + (this as? java.lang.Throwable)?.printStackTrace(printStream) + return byteOutputStream.toString() + } \ No newline at end of file