Incremental KAPT: simplify impacted types computation

Process aggregating types first, and when computing impacted types
compute isolating generated impacted by classpath changes first.
This commit is contained in:
Ivan Gavrilovic
2020-11-27 11:21:10 +00:00
committed by Mikhael Bogdanov
parent c7e5beece5
commit 05e47da458
3 changed files with 31 additions and 53 deletions
@@ -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)
}
@@ -55,49 +55,40 @@ class JavaClassCacheManager(val file: File) : Closeable {
val sourcesToReprocess = changedSources.toMutableSet()
val classNamesToReprocess = mutableListOf<String>()
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<String>): MutableSet<String> {
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)
}
@@ -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<String>) {