Add static modifier to nested kotlin classes
Nested classes in kotlin are static by default.
This CL updates KspHasModifiers to add the static
modifier when it is a nested kotlin class without the
inner modifier.
A possible alternative solution is to add `isInner` to XTypeElement
because Room is using isStatic as a proxy to discover inner classes.
I've not implemented that because removing isStatic is not very feasible
from XHasModifiers but we can do a followup CL to divide XHasModifiers
and remove isStatic from there.
Right now, KSP does not report INNER modifier for .class files which is
why I couldn't add a test with compiled code.
https://github.com/google/ksp/pull/232
I've also renamed KspTypeElementTest to XTypeElementTest since
it runs all but 1 test w/ both processors.
Bug: 160322705
Test: XTypeElementTest
Change-Id: Ie07382a8744b26eda3b4454d45ea74bfae71fd70
diff --git a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspHasModifiers.kt b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspHasModifiers.kt
index 1ab2cce..dd40fc9 100644
--- a/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspHasModifiers.kt
+++ b/room/compiler-processing/src/main/java/androidx/room/compiler/processing/ksp/KspHasModifiers.kt
@@ -75,6 +75,24 @@
private class Declaration(declaration: KSDeclaration) : KspHasModifiers(declaration)
+ private class ClassDeclaration(declaration: KSDeclaration) : KspHasModifiers(declaration) {
+ override fun isStatic(): Boolean {
+ if (declaration.isStatic()) {
+ return true
+ }
+ // inner classes in kotlin are static by default unless they have inner modifier.
+ // for .class files, there is currently a bug:
+ // https://github.com/google/ksp/pull/232 and once it is fixed, inner modifier will
+ // be reported for .class files as well.
+ if (declaration.origin != Origin.JAVA &&
+ declaration.parentDeclaration is KSClassDeclaration // nested class
+ ) {
+ return !declaration.modifiers.contains(Modifier.INNER)
+ }
+ return false
+ }
+ }
+
private class PropertyField(
declaration: KSPropertyDeclaration
) : KspHasModifiers(declaration) {
@@ -158,7 +176,7 @@
}
fun create(owner: KSClassDeclaration): XHasModifiers {
- return Declaration(owner)
+ return ClassDeclaration(owner)
}
}
}
diff --git a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeElementTest.kt b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt
similarity index 95%
rename from room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeElementTest.kt
rename to room/compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt
index 6780ed9..ddd18f3 100644
--- a/room/compiler-processing/src/test/java/androidx/room/compiler/processing/ksp/KspTypeElementTest.kt
+++ b/room/compiler-processing/src/test/java/androidx/room/compiler/processing/XTypeElementTest.kt
@@ -14,10 +14,8 @@
* limitations under the License.
*/
-package androidx.room.compiler.processing.ksp
+package androidx.room.compiler.processing
-import androidx.room.compiler.processing.XMethodElement
-import androidx.room.compiler.processing.XTypeElement
import androidx.room.compiler.processing.util.Source
import androidx.room.compiler.processing.util.XTestInvocation
import androidx.room.compiler.processing.util.getAllFieldNames
@@ -36,7 +34,7 @@
import org.junit.runners.JUnit4
@RunWith(JUnit4::class)
-class KspTypeElementTest {
+class XTypeElementTest {
@Test
fun qualifiedNames() {
val src1 = Source.kotlin(
@@ -164,7 +162,7 @@
@Test
fun modifiers() {
- val src = Source.kotlin(
+ val kotlinSrc = Source.kotlin(
"Foo.kt",
"""
open class OpenClass
@@ -173,9 +171,24 @@
interface MyInterface
class Final
private class PrivateClass
+ class OuterKotlinClass {
+ inner class InnerKotlinClass
+ class NestedKotlinClass
+ }
""".trimIndent()
)
- runProcessorTest(sources = listOf(src)) { invocation ->
+ val javaSrc = Source.java(
+ "OuterJavaClass",
+ """
+ public class OuterJavaClass {
+ public class InnerJavaClass {}
+ public static class NestedJavaClass {}
+ }
+ """.trimIndent()
+ )
+ runProcessorTest(
+ sources = listOf(kotlinSrc, javaSrc)
+ ) { invocation ->
fun getModifiers(element: XTypeElement): Set<String> {
val result = mutableSetOf<String>()
if (element.isAbstract()) result.add("abstract")
@@ -185,6 +198,7 @@
if (element.isPublic()) result.add("public")
if (element.isKotlinObject()) result.add("object")
if (element.isInterface()) result.add("interface")
+ if (element.isStatic()) result.add("static")
return result
}
@@ -212,6 +226,14 @@
listOf("final")
}
)
+ assertThat(getModifiers("OuterKotlinClass.InnerKotlinClass"))
+ .containsExactly("final", "public")
+ assertThat(getModifiers("OuterKotlinClass.NestedKotlinClass"))
+ .containsExactly("final", "public", "static")
+ assertThat(getModifiers("OuterJavaClass.InnerJavaClass"))
+ .containsExactly("public")
+ assertThat(getModifiers("OuterJavaClass.NestedJavaClass"))
+ .containsExactly("public", "static")
}
}