Support isolating APs that report multiple originating elements from the same file

It is possible for isolating annotation processor to report two or more
originating elements from the same source file when generating
sources/classes/resources. This commit makes sure the source file are
de-duped, so assertion that there is a single source file does not fail.

Test: IsolatingIncrementalProcessorsTest.testIsolatingWithMultipleOriginatingElements

This is improvement to https://youtrack.jetbrains.com/issue/KT-23880
This commit is contained in:
Ivan Gavrilovic
2019-05-21 11:21:03 +01:00
committed by Yan Zhulanow
parent 76f62da6ae
commit 1fa990b063
3 changed files with 30 additions and 3 deletions
@@ -124,15 +124,15 @@ internal class AnnotationProcessorDependencyCollector(private val runtimeProcTyp
}
}
private fun getSrcFiles(elements: Array<out Element?>): List<File> {
private fun getSrcFiles(elements: Array<out Element?>): Set<File> {
return elements.filterNotNull().mapNotNull { elem ->
var origin = elem
while (origin.enclosingElement != null && origin.enclosingElement !is PackageElement) {
origin = origin.enclosingElement
}
val uri = (origin as? Symbol.ClassSymbol)?.sourcefile?.toUri()?.takeIf { it.isAbsolute }
uri?.let { File(it) }
}
uri?.let { File(it).canonicalFile }
}.toSet()
}
enum class DeclaredProcType {
@@ -107,4 +107,17 @@ class IsolationgIncrementalProcessorTest {
), isolating[1].getGeneratedToSources()
)
}
@Test
fun testIsolatingWithMultipleOriginatingElements() {
val srcFiles = listOf("User.java", "Observable.java").map { File(TEST_DATA_DIR, it) }
val isolating = listOf(ReportTwoOriginElements().toIsolating())
runAnnotationProcessing(srcFiles, isolating, generatedSources)
assertEquals(
mapOf(
generatedSources.resolve("test/UserGenerated.java") to File("plugins/kapt3/kapt3-base/testData/runner/incremental/User.java").absoluteFile
), isolating[0].getGeneratedToSources()
)
}
}
@@ -145,6 +145,20 @@ class SimpleGeneratingIfTypeDoesNotExist: SimpleProcessor() {
}
}
return false
}
}
open class ReportTwoOriginElements : SimpleProcessor() {
override fun process(annotations: MutableSet<out TypeElement>, roundEnv: RoundEnvironment): Boolean {
if (annotations.isEmpty()) return false
roundEnv.getElementsAnnotatedWith(annotations.single()).forEach {
it as TypeElement
// Report 2 elements from the same file as originating
filer.createSourceFile("${it.qualifiedName}Generated", it, it).openWriter().use { it.write("") }
}
return false
}
}