Merge "Include raw output in processor tests" into androidx-main
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/AnnotatedString.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/AnnotatedString.kt
index 732c765..77f77cf 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/AnnotatedString.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/AnnotatedString.kt
@@ -126,10 +126,11 @@
* with the range [start, end) will be returned. When [start] is bigger than [end], an empty
* list will be returned.
*/
+ @Suppress("UNCHECKED_CAST")
fun getStringAnnotations(start: Int, end: Int): List<StringAnnotation> =
- annotations.filterIsInstance<Range<String>>().filter {
- intersect(start, end, it.start, it.end)
- }
+ annotations.filter {
+ it.item is String && intersect(start, end, it.start, it.end)
+ } as List<StringAnnotation>
/**
* Query all of the string annotations attached on this AnnotatedString.
@@ -140,10 +141,11 @@
* with the range [start, end) will be returned. When [start] is bigger than [end], an empty
* list will be returned.
*/
+ @Suppress("UNCHECKED_CAST")
fun getTtsAnnotations(start: Int, end: Int): List<Range<TtsAnnotation>> =
- annotations.filterIsInstance<Range<TtsAnnotation>>().filter {
- intersect(start, end, it.start, it.end)
- }
+ annotations.filter {
+ it.item is TtsAnnotation && intersect(start, end, it.start, it.end)
+ } as List<Range<TtsAnnotation>>
/**
* The information attached on the text such as a [SpanStyle].
diff --git a/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/AnnotatedStringBuilderTest.kt b/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/AnnotatedStringBuilderTest.kt
index 641b23cd..51643d7 100644
--- a/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/AnnotatedStringBuilderTest.kt
+++ b/compose/ui/ui-text/src/test/java/androidx/compose/ui/text/AnnotatedStringBuilderTest.kt
@@ -709,6 +709,38 @@
)
}
+ @Test
+ fun getAnnotation_separates_ttsAnnotation_and_stringAnnotation() {
+ val annotation1 = VerbatimTtsAnnotation("abc")
+ val annotation2 = "annotation"
+ val tag = "tag"
+ val buildResult = AnnotatedString.Builder().apply {
+ pushTtsAnnotation(annotation1)
+ append("Hello")
+ pushStringAnnotation(tag, annotation2)
+ append("world")
+ pop()
+ append("!")
+ pop()
+ }.toAnnotatedString()
+
+ // The final result is Helloworld!
+ // [ ] TtsAnnotation
+ // [ ] StringAnnotation
+ assertThat(buildResult.getTtsAnnotations(0, 5)).isEqualTo(
+ listOf(AnnotatedString.Range(annotation1, 0, 11, ""))
+ )
+ assertThat(buildResult.getTtsAnnotations(5, 6)).isEqualTo(
+ listOf(AnnotatedString.Range(annotation1, 0, 11, ""))
+ )
+
+ assertThat(buildResult.getStringAnnotations(0, 5)).isEmpty()
+ assertThat(buildResult.getStringAnnotations(5, 6)).isEqualTo(
+ listOf(AnnotatedString.Range(annotation2, 5, 10, tag))
+ )
+ assertThat(buildResult.getStringAnnotations(10, 11)).isEmpty()
+ }
+
private fun createAnnotatedString(
text: String,
color: Color = Color.Red,
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotationBox.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotationBox.kt
index b62e6ad..d478ac4 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotationBox.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotationBox.kt
@@ -132,7 +132,12 @@
}
}
is Array<*> -> mapNotNull { it?.readAs(returnType.componentType) }
- else -> error("unexpected type for array: $this / ${this::class.java}")
+ else -> {
+ // If array syntax is not used in java code, KSP might return it as a single
+ // item instead of list or array
+ // see: https://github.com/google/ksp/issues/214
+ listOf(this.readAs(returnType.componentType))
+ }
}
val resultArray = java.lang.reflect.Array.newInstance(
returnType.componentType,
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationBoxTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationBoxTest.kt
index 40cab24..b966fb6 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationBoxTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XAnnotationBoxTest.kt
@@ -17,6 +17,7 @@
package androidx.room.compiler.processing
import androidx.room.compiler.processing.testcode.JavaAnnotationWithDefaults
+import androidx.room.compiler.processing.testcode.JavaAnnotationWithTypeReferences
import androidx.room.compiler.processing.testcode.JavaEnum
import androidx.room.compiler.processing.testcode.MainAnnotation
import androidx.room.compiler.processing.testcode.OtherAnnotation
@@ -202,6 +203,30 @@
}
@Test
+ fun typeReferenceArray_singleItemInJava() {
+ val src = Source.java(
+ "Subject",
+ """
+ import androidx.room.compiler.processing.testcode.JavaAnnotationWithTypeReferences;
+ @JavaAnnotationWithTypeReferences(String.class)
+ class Subject {
+ }
+ """.trimIndent()
+ )
+ runProcessorTest(
+ sources = listOf(src)
+ ) { invocation ->
+ val subject = invocation.processingEnv.requireTypeElement("Subject")
+ val annotationValue = subject.toAnnotationBox(
+ JavaAnnotationWithTypeReferences::class
+ )?.getAsTypeList("value")
+ assertThat(annotationValue?.map { it.typeName }).containsExactly(
+ ClassName.get(String::class.java)
+ )
+ }
+ }
+
+ @Test
fun propertyAnnotations() {
val src = Source.kotlin(
"Foo.kt",
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/testcode/JavaAnnotationWithTypeReferences.java b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/testcode/JavaAnnotationWithTypeReferences.java
new file mode 100644
index 0000000..cd263ff
--- /dev/null
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/testcode/JavaAnnotationWithTypeReferences.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.room.compiler.processing.testcode;
+
+public @interface JavaAnnotationWithTypeReferences {
+ Class<?>[] value();
+}
diff --git a/room/compiler/src/main/kotlin/androidx/room/processor/Context.kt b/room/compiler/src/main/kotlin/androidx/room/processor/Context.kt
index 5bbeea0..484baaa 100644
--- a/room/compiler/src/main/kotlin/androidx/room/processor/Context.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/processor/Context.kt
@@ -101,8 +101,12 @@
val STRING: XType by lazy {
processingEnv.requireType("java.lang.String")
}
- val COLLECTION: XType by lazy {
- processingEnv.requireType("java.util.Collection")
+ val READONLY_COLLECTION: XType by lazy {
+ if (processingEnv.backend == XProcessingEnv.Backend.KSP) {
+ processingEnv.requireType("kotlin.collections.Collection")
+ } else {
+ processingEnv.requireType("java.util.Collection")
+ }
}
}
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt b/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
index b279c68..f12c2b1 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/TypeAdapterStore.kt
@@ -541,7 +541,7 @@
typeMirror: XType,
isMultipleParameter: Boolean
): QueryParameterAdapter? {
- if (context.COMMON_TYPES.COLLECTION.rawType.isAssignableFrom(typeMirror)) {
+ if (context.COMMON_TYPES.READONLY_COLLECTION.rawType.isAssignableFrom(typeMirror)) {
val typeArg = typeMirror.typeArguments.first().extendsBoundOrSelf()
// An adapter for the collection type arg wrapped in the built-in collection adapter.
val wrappedCollectionAdapter = findStatementValueBinder(typeArg, null)?.let {
diff --git a/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt b/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
index 1632335..e6feb02 100644
--- a/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
+++ b/room/compiler/src/test/kotlin/androidx/room/solver/TypeAdapterStoreTest.kt
@@ -22,7 +22,6 @@
import androidx.room.compiler.processing.XProcessingEnv
import androidx.room.compiler.processing.util.Source
import androidx.room.compiler.processing.util.XTestInvocation
-import androidx.room.compiler.processing.util.runKaptTest
import androidx.room.compiler.processing.util.runProcessorTest
import androidx.room.ext.GuavaUtilConcurrentTypeNames
import androidx.room.ext.L
@@ -42,6 +41,7 @@
import androidx.room.solver.binderprovider.LiveDataQueryResultBinderProvider
import androidx.room.solver.binderprovider.PagingSourceQueryResultBinderProvider
import androidx.room.solver.binderprovider.RxQueryResultBinderProvider
+import androidx.room.solver.query.parameter.CollectionQueryParameterAdapter
import androidx.room.solver.shortcut.binderprovider.GuavaListenableFutureDeleteOrUpdateMethodBinderProvider
import androidx.room.solver.shortcut.binderprovider.GuavaListenableFutureInsertMethodBinderProvider
import androidx.room.solver.shortcut.binderprovider.RxCallableDeleteOrUpdateMethodBinderProvider
@@ -74,7 +74,6 @@
@Test
fun testInvalidNonStaticInnerClass() {
- // TODO: (b/176180385)
val converter = Source.java(
"foo.bar.EmptyClass",
"""
@@ -115,7 +114,7 @@
}
""".trimIndent()
)
- runKaptTest(
+ runProcessorTest(
sources = listOf(entity, converter)
) { invocation ->
val typeElement =
@@ -843,6 +842,42 @@
}
}
+ @Test
+ fun findQueryParameterAdapter_collections() {
+ runProcessorTest { invocation ->
+ val store = TypeAdapterStore.create(
+ context = invocation.context
+ )
+ val javacCollectionTypes = listOf(
+ "java.util.Set",
+ "java.util.List",
+ "java.util.ArrayList"
+ )
+ val kotlinCollectionTypes = listOf(
+ "kotlin.collections.List",
+ "kotlin.collections.MutableList"
+ )
+ val collectionTypes = if (invocation.isKsp) {
+ javacCollectionTypes + kotlinCollectionTypes
+ } else {
+ javacCollectionTypes
+ }
+ collectionTypes.map { collectionType ->
+ invocation.processingEnv.getDeclaredType(
+ invocation.processingEnv.requireTypeElement(collectionType),
+ invocation.processingEnv.requireType(TypeName.INT).boxed()
+ )
+ }.forEach { type ->
+ val adapter = store.findQueryParameterAdapter(
+ typeMirror = type,
+ isMultipleParameter = true
+ )
+ assertThat(adapter).isNotNull()
+ assertThat(adapter).isInstanceOf(CollectionQueryParameterAdapter::class.java)
+ }
+ }
+ }
+
private fun createIntListToStringBinders(invocation: XTestInvocation): List<TypeConverter> {
val intType = invocation.processingEnv.requireType(Integer::class)
val listElement = invocation.processingEnv.requireTypeElement(java.util.List::class)