Fields that should be flagged with MissingJvmStatic are now flagged.
Public, non-const properties which are effective constants in a companion
object that are missing @JvmField annotation are now flagged with
MissingJvmStatic warning.
Bug: 138602561
Test: ./gradlew test
Change-Id: I02a8c8ee81e2db619413fdca4a588d1d9bb140f3
diff --git a/src/main/java/com/android/tools/metalava/KotlinInteropChecks.kt b/src/main/java/com/android/tools/metalava/KotlinInteropChecks.kt
index d88ed2a..8c37f34 100644
--- a/src/main/java/com/android/tools/metalava/KotlinInteropChecks.kt
+++ b/src/main/java/com/android/tools/metalava/KotlinInteropChecks.kt
@@ -26,6 +26,8 @@
import com.android.tools.metalava.model.TypeItem
import com.android.tools.metalava.model.visitors.ApiVisitor
import com.intellij.lang.java.lexer.JavaLexer
+import org.jetbrains.kotlin.lexer.KtTokens
+import org.jetbrains.kotlin.psi.KtObjectDeclaration
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.uast.kotlin.KotlinUField
@@ -137,16 +139,40 @@
if (modifiers.findAnnotation("kotlin.jvm.JvmField") == null) {
reporter.report(
Issues.MISSING_JVMSTATIC, field,
- "Companion object constants like ${field.name()} should be marked @JvmField for Java interoperability; see https://android.github.io/kotlin-guides/interop.html#companion-constants"
+ "Companion object constants like ${field.name()} should be marked @JvmField for Java interoperability; see https://developer.android.com/kotlin/interop#companion_constants"
)
} else if (modifiers.findAnnotation("kotlin.jvm.JvmStatic") != null) {
reporter.report(
Issues.MISSING_JVMSTATIC, field,
- "Companion object constants like ${field.name()} should be using @JvmField, not @JvmStatic; see https://android.github.io/kotlin-guides/interop.html#companion-constants"
+ "Companion object constants like ${field.name()} should be using @JvmField, not @JvmStatic; see https://developer.android.com/kotlin/interop#companion_constants"
)
}
}
}
+ } else if (sourcePsi is KtObjectDeclaration && sourcePsi.isCompanion()) {
+ // We are checking if we have public properties that we can expect to be constant
+ // (that is, declared via `val`) but that aren't declared 'const' in a companion
+ // object that are not annotated with @JvmField or annotated with @JvmStatic
+ // https://developer.android.com/kotlin/interop#companion_constants
+ val ktProperties = sourcePsi.declarations.filter { declaration ->
+ declaration is KtProperty && !declaration.isVar && !declaration.hasModifier(
+ KtTokens.CONST_KEYWORD
+ ) && declaration.annotationEntries.filter {
+ annotationEntry -> annotationEntry.shortName!!.asString() == "JvmField"
+ }.isEmpty() }
+ for (ktProperty in ktProperties) {
+ if (ktProperty.annotationEntries.filter { annotationEntry -> annotationEntry.shortName!!.asString() == "JvmStatic" }.isEmpty()) {
+ reporter.report(
+ Issues.MISSING_JVMSTATIC, ktProperty,
+ "Companion object constants like ${ktProperty.name} should be marked @JvmField for Java interoperability; see https://developer.android.com/kotlin/interop#companion_constants"
+ )
+ } else {
+ reporter.report(
+ Issues.MISSING_JVMSTATIC, ktProperty,
+ "Companion object constants like ${ktProperty.name} should be using @JvmField, not @JvmStatic; see https://developer.android.com/kotlin/interop#companion_constants"
+ )
+ }
+ }
}
}
}
@@ -201,12 +227,12 @@
if (field.modifiers.findAnnotation("kotlin.jvm.JvmStatic") != null) {
reporter.report(
Errors.MISSING_JVMSTATIC, method,
- "Companion object constants should be using @JvmField, not @JvmStatic; see https://android.github.io/kotlin-guides/interop.html#companion-constants"
+ "Companion object constants should be using @JvmField, not @JvmStatic; see https://developer.android.com/kotlin/interop#companion_constants"
)
} else if (field.modifiers.findAnnotation("kotlin.jvm.JvmField") == null) {
reporter.report(
Errors.MISSING_JVMSTATIC, method,
- "Companion object constants should be marked @JvmField for Java interoperability; see https://android.github.io/kotlin-guides/interop.html#companion-constants"
+ "Companion object constants should be marked @JvmField for Java interoperability; see https://developer.android.com/kotlin/interop#companion_constants"
)
}
}
@@ -215,7 +241,7 @@
} else if (method.modifiers.findAnnotation("kotlin.jvm.JvmStatic") == null) {
reporter.report(
Issues.MISSING_JVMSTATIC, method,
- "Companion object methods like ${method.name()} should be marked @JvmStatic for Java interoperability; see https://android.github.io/kotlin-guides/interop.html#companion-functions"
+ "Companion object methods like ${method.name()} should be marked @JvmStatic for Java interoperability; see https://developer.android.com/kotlin/interop#companion_functions"
)
}
}
diff --git a/src/test/java/com/android/tools/metalava/KotlinInteropChecksTest.kt b/src/test/java/com/android/tools/metalava/KotlinInteropChecksTest.kt
index 49a472c..11ff9fc 100644
--- a/src/test/java/com/android/tools/metalava/KotlinInteropChecksTest.kt
+++ b/src/test/java/com/android/tools/metalava/KotlinInteropChecksTest.kt
@@ -106,8 +106,10 @@
check(
extraArguments = arrayOf(ARG_CHECK_KOTLIN_INTEROP),
warnings = """
- src/test/pkg/Foo.kt:10: warning: Companion object constants like WRONG2 should be using @JvmField, not @JvmStatic; see https://android.github.io/kotlin-guides/interop.html#companion-constants [MissingJvmstatic]
- src/test/pkg/Foo.kt:13: warning: Companion object methods like missing should be marked @JvmStatic for Java interoperability; see https://android.github.io/kotlin-guides/interop.html#companion-functions [MissingJvmstatic]
+ src/test/pkg/Foo.kt:8: warning: Companion object constants like BIG_INTEGER_ONE should be marked @JvmField for Java interoperability; see https://developer.android.com/kotlin/interop#companion_constants [MissingJvmstatic]
+ src/test/pkg/Foo.kt:10: warning: Companion object constants like WRONG should be using @JvmField, not @JvmStatic; see https://developer.android.com/kotlin/interop#companion_constants [MissingJvmstatic]
+ src/test/pkg/Foo.kt:11: warning: Companion object constants like WRONG2 should be using @JvmField, not @JvmStatic; see https://developer.android.com/kotlin/interop#companion_constants [MissingJvmstatic]
+ src/test/pkg/Foo.kt:14: warning: Companion object methods like missing should be marked @JvmStatic for Java interoperability; see https://developer.android.com/kotlin/interop#companion_functions [MissingJvmstatic]
""",
sourceFiles = arrayOf(
kotlin(
@@ -119,8 +121,9 @@
fun ok1() { }
companion object {
const val INTEGER_ONE = 1
- var BIG_INTEGER_ONE = BigInteger.ONE
- @JvmStatic val WRONG = 2 // not yet flagged
+ val BIG_INTEGER_ONE = BigInteger.ONE
+ var ok = 1
+ @JvmStatic val WRONG = 2
@JvmStatic @JvmField val WRONG2 = 2
@JvmField val ok3 = 3