Merge "Update KSP to alpha 06" into androidx-main
diff --git a/buildSrc/build_dependencies.gradle b/buildSrc/build_dependencies.gradle
index 935497b..7d18739 100644
--- a/buildSrc/build_dependencies.gradle
+++ b/buildSrc/build_dependencies.gradle
@@ -24,7 +24,7 @@
build_versions.kotlin = "1.4.31"
build_versions.kotlin_coroutines = "1.4.3"
-build_versions.ksp = "1.4.30-1.0.0-alpha05"
+build_versions.ksp = "1.4.31-1.0.0-alpha06"
build_versions.hilt = "2.33-beta"
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSTypeExt.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSTypeExt.kt
index 865214f..075f0ea 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSTypeExt.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KSTypeExt.kt
@@ -61,9 +61,6 @@
// TODO: https://issuetracker.google.com/issues/168639183
val qualified = qualifiedName?.asString() ?: return ERROR_TYPE_NAME
val jvmSignature = resolver.mapToJvmSignature(this)
- // https://github.com/google/ksp/commit/964e6f87a55e8ac159dbc37b4a70fc07a0b02e34
- // jvmSignature will be nullable in alpha06
- @Suppress("SENSELESS_COMPARISON")
if (jvmSignature != null && jvmSignature.isNotBlank()) {
return jvmSignature.typeNameFromJvmSignature()
}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotated.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotated.kt
index 0cf6f88..180ceec 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotated.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspAnnotated.kt
@@ -17,7 +17,6 @@
package androidx.room.compiler.processing.ksp
import androidx.room.compiler.processing.InternalXAnnotated
-import androidx.room.compiler.processing.XAnnotated
import androidx.room.compiler.processing.XAnnotationBox
import com.google.devtools.ksp.symbol.AnnotationUseSiteTarget
import com.google.devtools.ksp.symbol.KSAnnotated
@@ -79,8 +78,6 @@
}
}
- operator fun plus(other: KspAnnotated): XAnnotated = Combined(env, this, other)
-
private class KSAnnotatedDelegate(
env: KspProcessingEnv,
private val delegate: KSAnnotated,
@@ -99,16 +96,6 @@
}
}
- private class Combined(
- env: KspProcessingEnv,
- private val first: KspAnnotated,
- private val second: KspAnnotated
- ) : KspAnnotated(env) {
- override fun annotations(): Sequence<KSAnnotation> {
- return first.annotations() + second.annotations()
- }
- }
-
/**
* TODO: The implementation of UseSiteFilter is not 100% correct until
* https://github.com/google/ksp/issues/96 is fixed.
@@ -125,35 +112,26 @@
fun accept(annotation: KSAnnotation): Boolean
private class Impl(
- val acceptNull: Boolean,
val acceptedTarget: AnnotationUseSiteTarget
) : UseSiteFilter {
override fun accept(annotation: KSAnnotation): Boolean {
val target = annotation.useSiteTarget
- return if (target == null) {
- acceptNull
- } else {
- acceptedTarget == target
- }
+ return target == null || acceptedTarget == target
}
}
- /**
- * TODO: We should be able to remove use site filters once
- * https://github.com/google/ksp/issues/355 is fixed.
- */
companion object {
- val FIELD: UseSiteFilter = Impl(true, AnnotationUseSiteTarget.FIELD)
- val PROPERTY_SETTER_PARAMETER: UseSiteFilter =
- Impl(false, AnnotationUseSiteTarget.SETPARAM)
- val METHOD_PARAMETER: UseSiteFilter = Impl(true, AnnotationUseSiteTarget.PARAM)
val NO_USE_SITE = object : UseSiteFilter {
override fun accept(annotation: KSAnnotation): Boolean {
return annotation.useSiteTarget == null
}
}
- val NO_USE_SITE_OR_GETTER: UseSiteFilter = Impl(true, AnnotationUseSiteTarget.GET)
- val NO_USE_SITE_OR_SETTER: UseSiteFilter = Impl(true, AnnotationUseSiteTarget.SET)
+ val NO_USE_SITE_OR_FIELD: UseSiteFilter = Impl(AnnotationUseSiteTarget.FIELD)
+ val NO_USE_SITE_OR_METHOD_PARAMETER: UseSiteFilter =
+ Impl(AnnotationUseSiteTarget.PARAM)
+ val NO_USE_SITE_OR_GETTER: UseSiteFilter = Impl(AnnotationUseSiteTarget.GET)
+ val NO_USE_SITE_OR_SETTER: UseSiteFilter = Impl(AnnotationUseSiteTarget.SET)
+ val NO_USE_SITE_OR_SET_PARAM: UseSiteFilter = Impl(AnnotationUseSiteTarget.SETPARAM)
}
}
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt
index 73fdc00..8d5f6ac 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspExecutableParameterElement.kt
@@ -19,7 +19,7 @@
import androidx.room.compiler.processing.XAnnotated
import androidx.room.compiler.processing.XExecutableParameterElement
import androidx.room.compiler.processing.XType
-import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.METHOD_PARAMETER
+import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.NO_USE_SITE_OR_METHOD_PARAMETER
import com.google.devtools.ksp.symbol.KSValueParameter
internal class KspExecutableParameterElement(
@@ -28,7 +28,7 @@
val parameter: KSValueParameter
) : KspElement(env, parameter),
XExecutableParameterElement,
- XAnnotated by KspAnnotated.create(env, parameter, METHOD_PARAMETER) {
+ XAnnotated by KspAnnotated.create(env, parameter, NO_USE_SITE_OR_METHOD_PARAMETER) {
override val equalityItems: Array<out Any?>
get() = arrayOf(method, parameter)
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt
index 5325dc5..d4e4b33 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspFieldElement.kt
@@ -21,7 +21,7 @@
import androidx.room.compiler.processing.XHasModifiers
import androidx.room.compiler.processing.XType
import androidx.room.compiler.processing.XTypeElement
-import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.FIELD
+import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.NO_USE_SITE_OR_FIELD
import com.google.devtools.ksp.symbol.KSPropertyDeclaration
internal class KspFieldElement(
@@ -31,7 +31,7 @@
) : KspElement(env, declaration),
XFieldElement,
XHasModifiers by KspHasModifiers.create(declaration),
- XAnnotated by KspAnnotated.create(env, declaration, FIELD) {
+ XAnnotated by KspAnnotated.create(env, declaration, NO_USE_SITE_OR_FIELD) {
override val equalityItems: Array<out Any?> by lazy {
arrayOf(declaration, containing)
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/ResolverExt.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/ResolverExt.kt
index 799ae1307..8a290f1 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/ResolverExt.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/ResolverExt.kt
@@ -113,8 +113,6 @@
declaration: KSFunctionDeclaration
): String {
return try {
- // https://github.com/google/ksp/commit/964e6f87a55e8ac159dbc37b4a70fc07a0b02e34
- @Suppress("USELESS_ELVIS") // this will be nullable in alpha06
getJvmName(declaration) ?: declaration.simpleName.asString()
} catch (cannotFindDeclaration: IllegalStateException) {
// TODO remove this catch once that issue is fixed.
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
index ca7bbdf..e5bc888 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/synthetic/KspSyntheticPropertyMethodElement.kt
@@ -25,10 +25,9 @@
import androidx.room.compiler.processing.XType
import androidx.room.compiler.processing.XTypeElement
import androidx.room.compiler.processing.ksp.KspAnnotated
-import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.NO_USE_SITE
import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.NO_USE_SITE_OR_GETTER
import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.NO_USE_SITE_OR_SETTER
-import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.PROPERTY_SETTER_PARAMETER
+import androidx.room.compiler.processing.ksp.KspAnnotated.UseSiteFilter.Companion.NO_USE_SITE_OR_SET_PARAM
import androidx.room.compiler.processing.ksp.KspFieldElement
import androidx.room.compiler.processing.ksp.KspHasModifiers
import androidx.room.compiler.processing.ksp.KspProcessingEnv
@@ -206,12 +205,8 @@
) : XExecutableParameterElement,
XAnnotated by KspAnnotated.create(
env = env,
- delegate = origin.field.declaration,
- filter = PROPERTY_SETTER_PARAMETER
- ) + KspAnnotated.create(
- env = env,
delegate = origin.field.declaration.setter?.parameter,
- filter = NO_USE_SITE
+ filter = NO_USE_SITE_OR_SET_PARAM
) {
override val name: String by lazy {
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSTypeExtTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSTypeExtTest.kt
index 2959b466..c9de74e 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSTypeExtTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KSTypeExtTest.kt
@@ -21,10 +21,12 @@
import androidx.room.compiler.processing.util.CompilationTestCapabilities
import androidx.room.compiler.processing.util.Source
import androidx.room.compiler.processing.util.className
+import androidx.room.compiler.processing.util.compileFiles
import androidx.room.compiler.processing.util.kspResolver
import androidx.room.compiler.processing.util.runKaptTest
import androidx.room.compiler.processing.util.runKspTest
import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
import com.google.devtools.ksp.getDeclaredFunctions
import com.google.devtools.ksp.getDeclaredProperties
import com.google.devtools.ksp.isConstructor
@@ -41,85 +43,114 @@
class KSTypeExtTest {
@Test
fun kotlinTypeName() {
- val subjectSrc = Source.kotlin(
- "Foo.kt",
- """
- package foo.bar;
- import kotlin.collections.*
- class Baz {
- val intField : Int = TODO()
- val listOfInts : List<Int> = TODO()
- val mutableMapOfAny = mutableMapOf<String, Any?>()
- val nested:Nested = TODO()
- class Nested {
+ fun createSubject(pkg: String): Source {
+ return Source.kotlin(
+ "Foo.kt",
+ """
+ package $pkg
+ import kotlin.collections.*
+ class Baz {
+ val intField : Int = TODO()
+ val listOfInts : List<Int> = TODO()
+ val mutableMapOfAny = mutableMapOf<String, Any?>()
+ val nested:Nested = TODO()
+ class Nested {
+ }
}
+ """.trimIndent()
+ )
+ }
+
+ val subjectSrc = createSubject(pkg = "main")
+ val classpath = compileFiles(listOf(createSubject(pkg = "lib")))
+ runKspTest(sources = listOf(subjectSrc), classpath = listOf(classpath)) { invocation ->
+ listOf("main", "lib").map {
+ it to invocation.kspResolver.requireClass("$it.Baz")
+ }.forEach { (pkg, subject) ->
+ assertThat(subject.propertyType("intField").typeName(invocation.kspResolver))
+ .isEqualTo(TypeName.INT)
+ assertThat(subject.propertyType("listOfInts").typeName(invocation.kspResolver))
+ .isEqualTo(
+ ParameterizedTypeName.get(
+ List::class.className(),
+ TypeName.INT.box()
+ )
+ )
+ assertThat(subject.propertyType("mutableMapOfAny").typeName(invocation.kspResolver))
+ .isEqualTo(
+ ParameterizedTypeName.get(
+ Map::class.className(),
+ String::class.className(),
+ TypeName.OBJECT,
+ )
+ )
+ val typeName = subject.propertyType("nested").typeName(invocation.kspResolver)
+ check(typeName is ClassName)
+ assertThat(typeName.packageName()).isEqualTo(pkg)
+ assertThat(typeName.simpleNames()).containsExactly("Baz", "Nested")
}
- """.trimIndent()
- )
- runKspTest(sources = listOf(subjectSrc)) { invocation ->
- val subject = invocation.kspResolver.requireClass("foo.bar.Baz")
- assertThat(subject.propertyType("intField").typeName(invocation.kspResolver))
- .isEqualTo(TypeName.INT)
- assertThat(subject.propertyType("listOfInts").typeName(invocation.kspResolver))
- .isEqualTo(
- ParameterizedTypeName.get(
- List::class.className(),
- TypeName.INT.box()
- )
- )
- assertThat(subject.propertyType("mutableMapOfAny").typeName(invocation.kspResolver))
- .isEqualTo(
- ParameterizedTypeName.get(
- Map::class.className(),
- String::class.className(),
- TypeName.OBJECT,
- )
- )
- val typeName = subject.propertyType("nested").typeName(invocation.kspResolver)
- check(typeName is ClassName)
- assertThat(typeName.packageName()).isEqualTo("foo.bar")
- assertThat(typeName.simpleNames()).containsExactly("Baz", "Nested")
}
}
@Test
fun javaTypeName() {
- val subjectSrc = Source.java(
- "Baz",
- """
- import java.util.List;
- class Baz {
- int intField;
- List<Integer> listOfInts;
- List incompleteGeneric;
- Nested nested;
- static class Nested {
+ fun createSubject(pkg: String): Source {
+ return Source.java(
+ "$pkg.Baz",
+ """
+ package $pkg;
+
+ import java.util.List;
+ class Baz {
+ int intField;
+ List<Integer> listOfInts;
+ List incompleteGeneric;
+ Nested nested;
+ static class Nested {
+ }
}
+ """.trimIndent()
+ )
+ }
+
+ val subjectSrc = createSubject(pkg = "main")
+ val classpath = compileFiles(listOf(createSubject(pkg = "lib")))
+ runKspTest(sources = listOf(subjectSrc), classpath = listOf(classpath)) { invocation ->
+ listOf("main.Baz", "lib.Baz").map {
+ invocation.kspResolver.requireClass(it)
+ }.forEach { subject ->
+ assertWithMessage(subject.qualifiedName!!.asString())
+ .that(
+ subject.propertyType("intField").typeName(invocation.kspResolver)
+ ).isEqualTo(TypeName.INT)
+ assertWithMessage(subject.qualifiedName!!.asString())
+ .that(
+ subject.propertyType("listOfInts").typeName(invocation.kspResolver)
+ ).isEqualTo(
+ ParameterizedTypeName.get(
+ List::class.className(),
+ TypeName.INT.box()
+ )
+ )
+ val propertyType = subject.propertyType("incompleteGeneric")
+ val typeName = propertyType.typeName(invocation.kspResolver)
+ assertWithMessage(subject.qualifiedName!!.asString())
+ .that(
+ typeName
+ ).isEqualTo(
+ // kotlin does not have raw types hence it becomes List<Object>
+ ParameterizedTypeName.get(
+ List::class.java,
+ Object::class.java
+ )
+ )
+ val nestedTypeName = subject.propertyType("nested").typeName(invocation.kspResolver)
+ assertWithMessage(subject.qualifiedName!!.asString())
+ .that(nestedTypeName)
+ .isEqualTo(
+ ClassName.get(subject.packageName.asString(), "Baz", "Nested")
+ )
}
- """.trimIndent()
- )
- runKspTest(sources = listOf(subjectSrc)) { invocation ->
- val subject = invocation.kspResolver.requireClass("Baz")
- assertThat(
- subject.propertyType("intField").typeName(invocation.kspResolver)
- ).isEqualTo(TypeName.INT)
- assertThat(
- subject.propertyType("listOfInts").typeName(invocation.kspResolver)
- ).isEqualTo(
- ParameterizedTypeName.get(
- List::class.className(),
- TypeName.INT.box()
- )
- )
- assertThat(
- subject.propertyType("incompleteGeneric").typeName(invocation.kspResolver)
- ).isEqualTo(
- List::class.className()
- )
- assertThat(subject.propertyType("nested").typeName(invocation.kspResolver))
- .isEqualTo(
- ClassName.get("", "Baz", "Nested")
- )
}
}
@@ -170,63 +201,84 @@
@Test
fun kaptGoldenTest() {
CompilationTestCapabilities.assumeKspIsEnabled()
- val src = Source.kotlin(
- "Foo.kt",
- """
- class MyType
- class MyGeneric<T>
- class Subject {
- fun method1():MyGeneric<MyType> = TODO()
- fun method2(items: MyGeneric<in MyType>): MyType = TODO()
- fun method3(items: MyGeneric<out MyType>): MyType = TODO()
- fun method4(items: MyGeneric<MyType>): MyType = TODO()
- fun method5(): MyGeneric<out MyType> = TODO()
- fun method6(): MyGeneric<in MyType> = TODO()
- fun method7(): MyGeneric<MyType> = TODO()
- fun method8(): MyGeneric<*> = TODO()
- fun method9(args : Array<Int>):Array<Array<String>> = TODO()
- fun method10(args : Array<Array<Int>>):Array<String> = TODO()
- }
- """.trimIndent()
- )
- // methodName -> returnType, ...paramTypes
+ fun createSubject(pkg: String): Source {
+ return Source.kotlin(
+ "Foo.kt",
+ """
+ package $pkg
+ class MyType
+ class MyGeneric<T>
+ class Subject {
+ fun method1():MyGeneric<MyType> = TODO()
+ fun method2(items: MyGeneric<in MyType>): MyType = TODO()
+ fun method3(items: MyGeneric<out MyType>): MyType = TODO()
+ fun method4(items: MyGeneric<MyType>): MyType = TODO()
+ fun method5(): MyGeneric<out MyType> = TODO()
+ fun method6(): MyGeneric<in MyType> = TODO()
+ fun method7(): MyGeneric<MyType> = TODO()
+ // Since ksp alpha06, * projection information is always converted to
+ // STAR:Any?, and it worked that way since alpha01 for .class files.
+ // It is no different than missing type arguments (e.g.
+ // KSClassDeclaration.asStarProjectedType()). Keeping the TypeParameter name is
+ // important to stay close to JavaAP hence we don't test this explicit *
+ // projection case anymore.
+ // fun method8(): MyGeneric<*> = TODO()
+ fun method9(args : Array<Int>):Array<Array<String>> = TODO()
+ fun method10(args : Array<Array<Int>>):Array<String> = TODO()
+ }
+ """.trimIndent()
+ )
+ }
+
+ val src = createSubject(pkg = "main")
+ val classpath = compileFiles(listOf(createSubject(pkg = "lib")))
+ // classQName.methodName -> returnType, ...paramTypes
val golden = mutableMapOf<String, List<TypeName>>()
runKaptTest(
- sources = listOf(src)
+ sources = listOf(src), classpath = listOf(classpath)
) { invocation ->
- val env = (invocation.processingEnv as JavacProcessingEnv)
- val subject = env.delegate.elementUtils.getTypeElement("Subject")
- ElementFilter.methodsIn(subject.enclosedElements).map { method ->
- val types = listOf(method.returnType.safeTypeName()) +
- method.parameters.map {
- it.asType().safeTypeName()
- }
- golden[method.simpleName.toString()] = types
+ listOf("main.Subject", "lib.Subject").map {
+ val env = (invocation.processingEnv as JavacProcessingEnv)
+ env.delegate.elementUtils.getTypeElement(it)
+ }.forEach { subject ->
+ val keyPrefix = subject.qualifiedName.toString() + "."
+ ElementFilter.methodsIn(subject.enclosedElements).map { method ->
+ val types = listOf(method.returnType.safeTypeName()) +
+ method.parameters.map {
+ it.asType().safeTypeName()
+ }
+ golden[keyPrefix + method.simpleName.toString()] = types
+ }
}
}
val kspResults = mutableMapOf<String, List<TypeName>>()
runKspTest(
- sources = listOf(src)
+ sources = listOf(src), classpath = listOf(classpath)
) { invocation ->
- val env = (invocation.processingEnv as KspProcessingEnv)
- val subject = env.resolver.requireClass("Subject")
- subject.getDeclaredFunctions()
- .filterNot {
- // ElementFilter.methods in do not include constructors
- it.isConstructor()
- }.forEach { method ->
- val types = listOf(
- method.returnType.typeName(
+ listOf("main.Subject", "lib.Subject").map {
+ val env = (invocation.processingEnv as KspProcessingEnv)
+ env.resolver.requireClass(it)
+ }.forEach { subject ->
+ val keyPrefix = subject.qualifiedName!!.asString() + "."
+ subject.getDeclaredFunctions()
+ .filterNot {
+ // ElementFilter.methods in do not include constructors
+ it.isConstructor()
+ }.forEach { method ->
+ val returnTypeName = method.returnType.typeName(
invocation.kspResolver
)
- ) +
- method.parameters.map {
- it.type.typeName(
- invocation.kspResolver
- )
- }
- kspResults[method.simpleName.asString()] = types
- }
+ val types = listOf(
+ returnTypeName
+ ) +
+ method.parameters.map {
+ it.type.typeName(
+ invocation.kspResolver
+ )
+ }
+ kspResults[keyPrefix + method.simpleName.asString()] = types
+ }
+ }
}
// make sure we grabbed some values to ensure test is working
assertThat(golden).isNotEmpty()
diff --git a/room/integration-tests/kotlintestapp/build.gradle b/room/integration-tests/kotlintestapp/build.gradle
index 4e89662..a378d53 100644
--- a/room/integration-tests/kotlintestapp/build.gradle
+++ b/room/integration-tests/kotlintestapp/build.gradle
@@ -131,6 +131,13 @@
testImplementation(MOCKITO_CORE)
}
+if (useKsp) {
+ ksp {
+ arg("room.schemaLocation","$projectDir/schemas".toString())
+ arg("room.expandProjection", "true")
+ }
+}
+
// Allow usage of Kotlin's @OptIn.
tasks.withType(KotlinCompile).configureEach {
kotlinOptions {