Merge "Don't warn for Kotlin synthetic metadata found." into androidx-main am: aea998fd46
Original change: https://android-review.googlesource.com/c/platform/frameworks/support/+/2609040
Change-Id: I00448a7a010aa050661073452021f7f68dcb3204
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/CompilationResultSubject.kt b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/CompilationResultSubject.kt
index 83ccfd4..405c5a1 100644
--- a/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/CompilationResultSubject.kt
+++ b/room/room-compiler-processing-testing/src/main/java/androidx/room/compiler/processing/util/CompilationResultSubject.kt
@@ -31,6 +31,7 @@
import com.google.testing.compile.Compilation
import java.util.regex.Pattern
import javax.tools.Diagnostic
+import org.junit.AssumptionViolatedException
/**
* Holds the information about a test compilation result.
@@ -415,6 +416,11 @@
internal fun assertNoProcessorAssertionErrors() {
val processingException = compilationResult.processor.getProcessingException()
if (processingException != null) {
+ // processor has an assumption violation, re-throw so test case does not generate
+ // a failure
+ if (processingException is AssumptionViolatedException) {
+ throw processingException
+ }
// processor has an error which we want to throw but we also want the subject, hence
// we wrap it
throw CompilationAssertionError(
diff --git a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinClassMetadataUtils.kt b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinClassMetadataUtils.kt
index 9e8131c..3a0e081 100644
--- a/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinClassMetadataUtils.kt
+++ b/room/room-compiler-processing/src/main/java/androidx/room/compiler/processing/javac/kotlin/KotlinClassMetadataUtils.kt
@@ -166,12 +166,23 @@
element
)
}
- // TODO: Support more metadata kind (file facade, synthetic class, etc...)
return when (classMetadata) {
is KotlinClassMetadata.Class -> KmClassContainer(classMetadata.toKmClass())
+ // Synthetic classes generated for various Kotlin features ($DefaultImpls,
+ // $WhenMappings, etc) are ignored because the data contained does not affect
+ // the metadata derived APIs. These classes are never referenced by user code but
+ // could be discovered by processors when inspecting inner classes.
+ is KotlinClassMetadata.SyntheticClass,
+ // Multi file classes are also ignored, the elements contained in these might be
+ // referenced by user code in method bodies but not part of the AST, however it
+ // is possible for a processor to discover them by inspecting elements under a
+ // package.
+ is KotlinClassMetadata.FileFacade,
+ is KotlinClassMetadata.MultiFileClassFacade,
+ is KotlinClassMetadata.MultiFileClassPart -> null
else -> {
env.delegate.messager.printMessage(
- Diagnostic.Kind.WARNING,
+ Diagnostic.Kind.ERROR,
"Unable to read Kotlin metadata due to unsupported metadata " +
"kind: $classMetadata.",
element
diff --git a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/javac/kotlin/KotlinMetadataElementTest.kt b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/javac/kotlin/KotlinMetadataElementTest.kt
index 5915327..43c856b 100644
--- a/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/javac/kotlin/KotlinMetadataElementTest.kt
+++ b/room/room-compiler-processing/src/test/java/androidx/room/compiler/processing/javac/kotlin/KotlinMetadataElementTest.kt
@@ -20,6 +20,7 @@
import androidx.room.compiler.processing.XProcessingEnvConfig
import androidx.room.compiler.processing.javac.JavacProcessingEnv
import androidx.room.compiler.processing.util.Source
+import androidx.room.compiler.processing.util.XTestInvocation
import androidx.room.compiler.processing.util.compileFiles
import androidx.room.compiler.processing.util.runJavaProcessorTest
import androidx.room.compiler.processing.util.runKaptTest
@@ -792,6 +793,111 @@
}
}
+ @Test
+ fun ignore_syntheticMetadata_defaultImpls() {
+ val src = Source.kotlin(
+ "Subject.kt",
+ """
+ interface Subject {
+ fun instance(): String = "Hello"
+ }
+ """.trimIndent()
+ )
+ simpleRun(
+ sources = listOf(src),
+ kotlincArgs = listOf("-Xjvm-default=disable")
+ ) {
+ val subjectElement = processingEnv.requireTypeElement("Subject.DefaultImpls")
+ // Call metadata derived API causing it to be read
+ assertThat(subjectElement.isKotlinObject()).isFalse()
+ assertCompilationResult {
+ hasNoWarnings()
+ }
+ }
+ }
+
+ @Test
+ fun ignore_syntheticMetadata_whenMappings() {
+ val src = Source.kotlin(
+ "Subject.kt",
+ """
+ class Subject {
+ enum class Fruit {
+ APPLE,
+ STRAWBERRY
+ }
+
+ fun printName(fruit: Fruit) {
+ println(
+ when(fruit) {
+ Fruit.APPLE -> "manzana"
+ Fruit.STRAWBERRY -> "fresa"
+ }
+ )
+ }
+ }
+ """.trimIndent()
+ )
+ simpleRun(
+ sources = listOf(src),
+ ) {
+ assertThat(processingEnv.findTypeElement("Subject.Fruit")).isNotNull()
+ val subjectElement = processingEnv.findTypeElement("Subject.WhenMappings")
+ // Currently $WhenMapping has the ACC_SYNTHETIC flag making it unreadable by
+ // annotation processors making it impossible to verify synthetic metadata is
+ // ignored.
+ ?: throw AssumptionViolatedException("No test if WhenMappings is not found")
+ // Call metadata derived API causing it to be read
+ assertThat(subjectElement.isKotlinObject()).isFalse()
+ assertCompilationResult {
+ hasNoWarnings()
+ }
+ }
+ }
+
+ @Test
+ fun ignore_fileFacadeMetadata() {
+ val aSrc = Source.kotlin(
+ "A.kt",
+ """
+ @file:JvmMultifileClass
+ @file:JvmName("Subject")
+
+ fun a() { }
+ """.trimIndent()
+ )
+ val bSrc = Source.kotlin(
+ "B.kt",
+ """
+ @file:JvmMultifileClass
+ @file:JvmName("Subject")
+
+ fun b() { }
+ """.trimIndent()
+ )
+ simpleRun(
+ sources = listOf(aSrc, bSrc),
+ ) {
+ // Find the multi file class facade element
+ val facadeElement = processingEnv.requireTypeElement("Subject")
+ // Call metadata derived API causing it to be read
+ assertThat(facadeElement.isKotlinObject()).isFalse()
+
+ // Try to find the multi file class part elements, currently these classes have the
+ // ACC_SYNTHETIC flag making them unreadable by annotation processors and impossible to
+ // verify that multi file metadata is ignored.
+ val facadePartOne = processingEnv.findTypeElement("Subject__AKt")
+ ?: throw AssumptionViolatedException("No test if MultiFileClassPart is not found")
+ assertThat(facadePartOne.isKotlinObject()).isFalse()
+ val facadePartTwo = processingEnv.findTypeElement("Subject__BKt")
+ ?: throw AssumptionViolatedException("No test if MultiFileClassPart is not found")
+ assertThat(facadePartTwo.isKotlinObject()).isFalse()
+ assertCompilationResult {
+ hasNoWarnings()
+ }
+ }
+ }
+
private fun TypeElement.getDeclaredMethods() = ElementFilter.methodsIn(enclosedElements)
private fun TypeElement.getDeclaredMethod(name: String) = getDeclaredMethods().first {
@@ -803,19 +909,24 @@
@Suppress("NAME_SHADOWING") // intentional
private fun simpleRun(
sources: List<Source> = emptyList(),
- handler: (ProcessingEnvironment) -> Unit
+ kotlincArgs: List<String> = emptyList(),
+ handler: XTestInvocation.(ProcessingEnvironment) -> Unit
) {
val (sources, classpath) = if (preCompiled) {
emptyList<Source>() to compileFiles(sources)
} else {
sources to emptyList()
}
- runKaptTest(sources = sources, classpath = classpath) {
+ runKaptTest(
+ sources = sources,
+ classpath = classpath,
+ kotlincArguments = kotlincArgs
+ ) {
val processingEnv = it.processingEnv
if (processingEnv !is JavacProcessingEnv) {
throw AssumptionViolatedException("This test only works for java/kapt compilation")
}
- handler(processingEnv.delegate)
+ it.handler(processingEnv.delegate)
}
}