From 05e47da4583789e3cfdf0b4a6578f3ac19756e2b Mon Sep 17 00:00:00 2001 From: Ivan Gavrilovic Date: Fri, 27 Nov 2020 11:21:10 +0000 Subject: [PATCH] Incremental KAPT: simplify impacted types computation Process aggregating types first, and when computing impacted types compute isolating generated impacted by classpath changes first. --- .../base/incremental/IncrementalAptCache.kt | 4 +- .../kotlin/kapt3/base/incremental/cache.kt | 75 +++++++------------ .../base/incremental/classStructureCache.kt | 5 +- 3 files changed, 31 insertions(+), 53 deletions(-) diff --git a/plugins/kapt3/kapt3-base/src/org/jetbrains/kotlin/kapt3/base/incremental/IncrementalAptCache.kt b/plugins/kapt3/kapt3-base/src/org/jetbrains/kotlin/kapt3/base/incremental/IncrementalAptCache.kt index bb3697dc4b0..adc0f4d5ad9 100644 --- a/plugins/kapt3/kapt3-base/src/org/jetbrains/kotlin/kapt3/base/incremental/IncrementalAptCache.kt +++ b/plugins/kapt3/kapt3-base/src/org/jetbrains/kotlin/kapt3/base/incremental/IncrementalAptCache.kt @@ -115,8 +115,8 @@ class IncrementalAptCache : Serializable { } /** Gets the originating type for the specified type generated by isolating AP. */ - fun getOriginForGeneratedIsolatingType(generatedType: String, sourceFileProvider: (String) -> File?): String { - val generatedFile = checkNotNull(sourceFileProvider(generatedType)) { "Unable to find source for $generatedType" } + fun getOriginForGeneratedIsolatingType(generatedType: String, sourceFileProvider: (String) -> File): String { + val generatedFile = sourceFileProvider(generatedType) return isolatingMapping.getValue(generatedFile) } diff --git a/plugins/kapt3/kapt3-base/src/org/jetbrains/kotlin/kapt3/base/incremental/cache.kt b/plugins/kapt3/kapt3-base/src/org/jetbrains/kotlin/kapt3/base/incremental/cache.kt index a6f8936cfb8..513321ecfff 100644 --- a/plugins/kapt3/kapt3-base/src/org/jetbrains/kotlin/kapt3/base/incremental/cache.kt +++ b/plugins/kapt3/kapt3-base/src/org/jetbrains/kotlin/kapt3/base/incremental/cache.kt @@ -55,49 +55,40 @@ class JavaClassCacheManager(val file: File) : Closeable { val sourcesToReprocess = changedSources.toMutableSet() val classNamesToReprocess = mutableListOf() - var shouldProcessAggregating = false - for (impactedType in impactedTypes) { - if (impactedType !in isolatingGeneratedTypes && impactedType !in aggregatingGeneratedTypes) { - // Reprocess only if original source - javaCache.getSourceForType(impactedType)?.let { - sourcesToReprocess.add(it) - } - } else if (impactedType in isolatingGeneratedTypes) { - // this is a generated type by isolating AP - val isolatingOrigin = aptCache.getOriginForGeneratedIsolatingType(impactedType, javaCache::getSourceForType) - if (isolatingOrigin in impactedTypes) { - // we'll process origin, no need to do it now - continue - } - val originSource = javaCache.getSourceForType(isolatingOrigin) - if (originSource?.extension == "java") { - sourcesToReprocess.add(originSource) - } else if (originSource?.extension == "class") { - // This is a generated .class file that we need to reprocess. - classNamesToReprocess.add(isolatingOrigin) - } else { - // This is a type from classpath that was used as origin, just ignore it. It is used just to remove the generated file. - } - } else { - // processed separately - shouldProcessAggregating = true - } - } - - if (shouldProcessAggregating || sourcesToReprocess.isNotEmpty() || classNamesToReprocess.isNotEmpty()) { + if (changedSources.isNotEmpty() || impactedTypes.isNotEmpty()) { for (aggregatingOrigin in aptCache.getAggregatingOrigins()) { if (aggregatingOrigin in impactedTypes) continue val originSource = javaCache.getSourceForType(aggregatingOrigin) - if (originSource?.extension == "java") { + if (originSource.extension == "java") { sourcesToReprocess.add(originSource) - } else if (originSource?.extension == "class") { + } else if (originSource.extension == "class") { // This is a generated .class file that we need to reprocess. classNamesToReprocess.add(aggregatingOrigin) } } + } + for (impactedType in impactedTypes) { + if (impactedType !in isolatingGeneratedTypes && impactedType !in aggregatingGeneratedTypes) { + sourcesToReprocess.add(javaCache.getSourceForType(impactedType)) + } else if (impactedType in isolatingGeneratedTypes) { + // this is a generated type by isolating AP + val isolatingOrigin = aptCache.getOriginForGeneratedIsolatingType(impactedType, javaCache::getSourceForType) + if (isolatingOrigin in impactedTypes || isolatingOrigin in dirtyClasspathFqNames) { + continue + } + val originSource = javaCache.getSourceForType(isolatingOrigin) + if (originSource.extension == "java") { + sourcesToReprocess.add(originSource) + } else if (originSource.extension == "class") { + classNamesToReprocess.add(isolatingOrigin) + } + } + } + + if (sourcesToReprocess.isNotEmpty() || classNamesToReprocess.isNotEmpty()) { // Invalidate state only if there are some files that will be reprocessed javaCache.invalidateDataForTypes(impactedTypes) aptCache.invalidateAggregating() @@ -111,27 +102,13 @@ class JavaClassCacheManager(val file: File) : Closeable { private fun getAllImpactedTypes(changes: Changes, aggregatingGeneratedTypes: Set): MutableSet { val impactedTypes = javaCache.getAllImpactedTypes(changes) - - /** - * In order to find all impacted types we do the following: - * - impacted types is a set of types that have changed from the previous compilation - * - if there is a changed source or a source file that is impacted by type changes, we'll need to run aggregating APs, so we - * invalidate all aggregating generated types, and add them to set of impacted types. - * - using this new impacted types set, we find all types generated by isolating APs with origins in those types - * - if there are some generated types by isolating APs, we'll need to run aggregating APs, so we invalidate all aggregating types - * and add them to impacted types. - * - using the final value of impacted types we get all generated types by isolating APs and add them to impacted types - */ + // check isolating with origins from the classpath + impactedTypes.addAll(aptCache.getIsolatingGeneratedTypesForOrigins(changes.dirtyFqNamesFromClasspath, javaCache::getTypesForFiles)) if (changes.sourceChanges.isNotEmpty() || impactedTypes.isNotEmpty()) { // Any source change or any source impacted by type change invalidates aggregating APs generated types impactedTypes.addAll(aggregatingGeneratedTypes) } - aptCache.getIsolatingGeneratedTypesForOrigins(changes.dirtyFqNamesFromClasspath, javaCache::getTypesForFiles).let { - if (it.isNotEmpty()) { - impactedTypes.addAll(it) - impactedTypes.addAll(aggregatingGeneratedTypes) - } - } + // now check isolating with origins in any of the impacted types aptCache.getIsolatingGeneratedTypesForOrigins(impactedTypes, javaCache::getTypesForFiles).let { impactedTypes.addAll(it) } diff --git a/plugins/kapt3/kapt3-base/src/org/jetbrains/kotlin/kapt3/base/incremental/classStructureCache.kt b/plugins/kapt3/kapt3-base/src/org/jetbrains/kotlin/kapt3/base/incremental/classStructureCache.kt index 0bf8dc97aa5..91e53ebe20b 100644 --- a/plugins/kapt3/kapt3-base/src/org/jetbrains/kotlin/kapt3/base/incremental/classStructureCache.kt +++ b/plugins/kapt3/kapt3-base/src/org/jetbrains/kotlin/kapt3/base/incremental/classStructureCache.kt @@ -10,6 +10,7 @@ import java.io.ObjectInputStream import java.io.ObjectOutputStream import java.io.Serializable import java.lang.IllegalArgumentException +import java.lang.IllegalStateException import java.net.URI /** @@ -147,13 +148,13 @@ class JavaClassCache() : Serializable { sourceCache.clear() } - fun getSourceForType(type: String): File? { + fun getSourceForType(type: String): File { sourceCache.forEach { (fileUri, typeInfo) -> if (type in typeInfo.getDeclaredTypes()) { return File(fileUri) } } - return null + throw IllegalStateException("Unable to find source file for type $type") } fun invalidateDataForTypes(impactedTypes: MutableSet) {