Skip to content

Commit

Permalink
Track binary output class names
Browse files Browse the repository at this point in the history
  • Loading branch information
Mikhael Bogdanov authored and max-kammerer committed Nov 24, 2020
1 parent 6748560 commit 42a9d64
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ dependencies {
// Workaround for missing transitive import of the common(project `kotlin-test-common`
// for `kotlin-test-jvm` into the IDE:
testCompileOnly(project(":kotlin-test:kotlin-test-common")) { isTransitive = false }
testCompileOnly("org.ow2.asm:asm:9.0")
}

// Aapt2 from Android Gradle Plugin 3.2 and below does not handle long paths on Windows.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import java.io.Serializable

class IncrementalAptCache : Serializable {

private val aggregatingGenerated: MutableSet<File> = mutableSetOf()
private val aggregatingGenerated: MutableMap<File, String?> = mutableMapOf()
private val aggregatedTypes: MutableSet<String> = linkedSetOf()
private val isolatingMapping: MutableMap<File, File> = mutableMapOf()
private val isolatingMapping: MutableMap<File, Pair<String?, File>> = mutableMapOf()
// Annotations claimed by aggregating annotation processors
private val aggregatingClaimedAnnotations: MutableSet<String> = mutableSetOf()

Expand All @@ -37,7 +37,11 @@ class IncrementalAptCache : Serializable {
}

aggregatingGenerated.clear()
aggregatingGenerated.addAll(aggregating.flatMap { it.getGeneratedToSources().keys })
aggregating.forEach {
it.getGeneratedToSourcesAll().mapValuesTo(aggregatingGenerated) { (_, value) ->
value?.first
}
}

aggregatingClaimedAnnotations.clear()
aggregatingClaimedAnnotations.addAll(aggregating.flatMap { it.supportedAnnotationTypes })
Expand All @@ -46,8 +50,8 @@ class IncrementalAptCache : Serializable {
aggregatedTypes.addAll(aggregating.flatMap { it.getAggregatedTypes() })

for (isolatingProcessor in isolating) {
isolatingProcessor.getGeneratedToSources().forEach {
isolatingMapping[it.key] = it.value!!
isolatingProcessor.getGeneratedToSourcesAll().forEach {
isolatingMapping[it.key] = it.value!!.first to it.value!!.second!!
}
}
return true
Expand All @@ -57,8 +61,8 @@ class IncrementalAptCache : Serializable {

/** Returns generated Java sources originating from aggregating APs. */
fun invalidateAggregating(): Pair<List<File>, List<String>> {
val dirtyAggregating = aggregatingGenerated.filter { it.extension == "java" }
aggregatingGenerated.forEach { it.delete() }
val dirtyAggregating = aggregatingGenerated.keys.filter { it.isJavaFileOrClass() }
aggregatingGenerated.forEach { it.key.delete() }
aggregatingGenerated.clear()

val dirtyAggregated = ArrayList(aggregatedTypes)
Expand All @@ -68,24 +72,30 @@ class IncrementalAptCache : Serializable {
}

/** Returns generated Java sources originating from the specified sources, and generated by isloating APs. */
fun invalidateIsolatingGenerated(fromSources: Set<File>): List<File> {
fun invalidateIsolatingGenerated(fromSources: Set<File>): Pair<List<File>, Set<String>> {
val allInvalidated = mutableListOf<File>()
val invalidatedClassIds = mutableSetOf<String>()
var changedSources = fromSources.toSet()

// We need to do it in a loop because mapping could be: [AGenerated.java -> A.java, AGeneratedGenerated.java -> AGenerated.java]
while (changedSources.isNotEmpty()) {
val generated = isolatingMapping.filter { changedSources.contains(it.value) }.keys
val generated = isolatingMapping.filter { changedSources.contains(it.value.second) }.keys
generated.forEach {
if (it.extension == "java") allInvalidated.add(it)
if (it.isJavaFileOrClass()) {
allInvalidated.add(it)
isolatingMapping[it]?.first?.let { invalidatedClassIds.add(it) }
}

it.delete()
isolatingMapping.remove(it)
}
changedSources = generated
}
return allInvalidated
return allInvalidated to invalidatedClassIds
}

private fun File.isJavaFileOrClass() = extension == "java" || extension == "class"

private fun invalidateCache() {
isIncremental = false
aggregatingGenerated.clear()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ class JavaClassCacheManager(val file: File) : Closeable {
is SourcesToReprocess.Incremental -> {
val toReprocess = filesToReprocess.toReprocess.toMutableSet()

val isolatingGenerated = aptCache.invalidateIsolatingGenerated(toReprocess)
val generatedDirtyTypes = javaCache.invalidateGeneratedTypes(isolatingGenerated).toMutableSet()
val (invalidatedIsolatingGenerated, invalidatedIsolatingId) = aptCache.invalidateIsolatingGenerated(toReprocess)
val generatedDirtyTypes = javaCache.invalidateGeneratedTypes(invalidatedIsolatingGenerated).toMutableSet() /*+*/

val aggregatedTypes = mutableListOf<String>()
if (!toReprocess.isEmpty()) {
// only if there are some files to reprocess we should invalidate the aggregating ones
Expand All @@ -66,6 +67,7 @@ class JavaClassCacheManager(val file: File) : Closeable {
aggregatedTypes.also {
it.removeAll(filesToReprocess.dirtyTypes)
it.removeAll(generatedDirtyTypes)
it.removeAll(invalidatedIsolatingId)
})
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class IncrementalProcessor(private val processor: Processor, private val kind: D

fun isUnableToRunIncrementally() = !kind.canRunIncrementally
fun getGeneratedToSources() = dependencyCollector.value.getGeneratedToSources()
fun getGeneratedToSourcesAll() = dependencyCollector.value.getGeneratedToSourcesAll()
fun getAggregatedTypes() = dependencyCollector.value.getAggregatedTypes()
fun getRuntimeType(): RuntimeProcType = dependencyCollector.value.getRuntimeType()

Expand All @@ -92,15 +93,15 @@ internal class IncrementalFiler(private val filer: Filer) : Filer by filer {

internal var dependencyCollector: AnnotationProcessorDependencyCollector? = null

override fun createSourceFile(name: CharSequence?, vararg originatingElements: Element?): JavaFileObject {
override fun createSourceFile(name: CharSequence, vararg originatingElements: Element?): JavaFileObject {
val createdSourceFile = filer.createSourceFile(name, *originatingElements)
dependencyCollector!!.add(createdSourceFile.toUri(), originatingElements)
dependencyCollector!!.add(createdSourceFile.toUri(), originatingElements, name.toString())
return createdSourceFile
}

override fun createClassFile(name: CharSequence?, vararg originatingElements: Element?): JavaFileObject {
override fun createClassFile(name: CharSequence, vararg originatingElements: Element?): JavaFileObject {
val createdClassFile = filer.createClassFile(name, *originatingElements)
dependencyCollector!!.add(createdClassFile.toUri(), originatingElements)
dependencyCollector!!.add(createdClassFile.toUri(), originatingElements, name.toString())
return createdClassFile
}

Expand All @@ -111,7 +112,7 @@ internal class IncrementalFiler(private val filer: Filer) : Filer by filer {
vararg originatingElements: Element?
): FileObject {
val createdResource = filer.createResource(location, pkg, relativeName, *originatingElements)
dependencyCollector!!.add(createdResource.toUri(), originatingElements)
dependencyCollector!!.add(createdResource.toUri(), originatingElements, null)

return createdResource
}
Expand All @@ -121,7 +122,7 @@ internal class AnnotationProcessorDependencyCollector(
private val runtimeProcType: RuntimeProcType,
private val warningCollector: (String) -> Unit
) {
private val generatedToSource = mutableMapOf<File, File?>()
private val generatedToSource = mutableMapOf<File, Pair<String?, File?>?>()
private val aggregatedTypes = mutableSetOf<String>()

private var isFullRebuild = !runtimeProcType.isIncremental
Expand Down Expand Up @@ -149,7 +150,7 @@ internal class AnnotationProcessorDependencyCollector(

val generatedFile = File(createdFile)
if (runtimeProcType == RuntimeProcType.AGGREGATING) {
generatedToSource[generatedFile] = null
generatedToSource[generatedFile] = classId to null
} else {
val srcFiles = getSrcFiles(originatingElements)
if (srcFiles.size != 1) {
Expand All @@ -159,12 +160,17 @@ internal class AnnotationProcessorDependencyCollector(
"but detected ${srcFiles.size}: [${srcFiles.joinToString()}]."
)
} else {
generatedToSource[generatedFile] = srcFiles.single()
generatedToSource[generatedFile] = classId to srcFiles.single()
}
}
}

internal fun getGeneratedToSources(): Map<File, File?> = if (isFullRebuild) emptyMap() else generatedToSource
internal fun getGeneratedToSources(): Map<File, File?> = if (isFullRebuild) emptyMap() else generatedToSource.mapValues { (_, value) ->
value?.second
}

internal fun getGeneratedToSourcesAll(): Map<File, Pair<String?, File?>?> =
if (isFullRebuild) emptyMap() else generatedToSource

internal fun getAggregatedTypes(): Set<String> = if (isFullRebuild) emptySet() else aggregatedTypes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class AnnotationProcessorDependencyCollectorTest {
fun testAggregating() {
val aggregating = AnnotationProcessorDependencyCollector(RuntimeProcType.AGGREGATING) {}
val generated = listOf("GeneratedA.java", "GeneratedB.java", "GeneratedC.java").map { File(it).toURI() }
generated.forEach { aggregating.add(it, emptyArray()) }
generated.forEach { aggregating.add(it, emptyArray(), null) }

assertEquals(aggregating.getGeneratedToSources(), generated.map { File(it) to null }.toMap())
assertEquals(aggregating.getRuntimeType(), RuntimeProcType.AGGREGATING)
Expand All @@ -27,7 +27,7 @@ class AnnotationProcessorDependencyCollectorTest {
fun testIsolatingWithoutOrigin() {
val warnings = mutableListOf<String>()
val isolating = AnnotationProcessorDependencyCollector(RuntimeProcType.ISOLATING) { s -> warnings.add(s) }
isolating.add(File("GeneratedA.java").toURI(), emptyArray())
isolating.add(File("GeneratedA.java").toURI(), emptyArray(), null)

assertEquals(isolating.getRuntimeType(), RuntimeProcType.NON_INCREMENTAL)
assertEquals(isolating.getGeneratedToSources(), emptyMap<File, File?>())
Expand All @@ -37,8 +37,8 @@ class AnnotationProcessorDependencyCollectorTest {
@Test
fun testNonIncremental() {
val nonIncremental = AnnotationProcessorDependencyCollector(RuntimeProcType.NON_INCREMENTAL) {}
nonIncremental.add(File("GeneratedA.java").toURI(), emptyArray())
nonIncremental.add(File("GeneratedB.java").toURI(), emptyArray())
nonIncremental.add(File("GeneratedA.java").toURI(), emptyArray(), null)
nonIncremental.add(File("GeneratedB.java").toURI(), emptyArray(), null)

assertEquals(nonIncremental.getRuntimeType(), RuntimeProcType.NON_INCREMENTAL)
assertEquals(nonIncremental.getGeneratedToSources(), emptyMap<File, File?>())
Expand Down

0 comments on commit 42a9d64

Please sign in to comment.