Fix bug in boolean logic related to generics nullability
Fixes: 222514899
Test: Two new unit tests
Change-Id: I55a480027ca89ca3acb0245df2428e8b69732c4b
diff --git a/src/main/java/com/android/tools/metalava/ApiLint.kt b/src/main/java/com/android/tools/metalava/ApiLint.kt
index 624945d..ce86222 100644
--- a/src/main/java/com/android/tools/metalava/ApiLint.kt
+++ b/src/main/java/com/android/tools/metalava/ApiLint.kt
@@ -1643,12 +1643,14 @@
}
private fun anySuperParameterIsNullable(parameter: ParameterItem): Boolean {
- return parameter.containingMethod().superMethods().any { superMethod ->
+ val supers = parameter.containingMethod().superMethods()
+ return supers.all { superMethod ->
// Disable check for generics
superMethod.parameters().none {
it.type().isTypeParameter()
- } &&
- superMethod.parameters().firstOrNull { param ->
+ }
+ } && supers.any { superMethod ->
+ superMethod.parameters().firstOrNull { param ->
parameter.parameterIndex == param.parameterIndex
}?.modifiers?.isNullable() ?: false
}
@@ -1663,16 +1665,18 @@
}
private fun anySuperParameterLacksNullnessInfo(parameter: ParameterItem): Boolean {
- return parameter.containingMethod().superMethods().any { superMethod ->
+ val supers = parameter.containingMethod().superMethods()
+ return supers.all { superMethod ->
// Disable check for generics
superMethod.parameters().none {
it.type().isTypeParameter()
- } &&
- !(
- superMethod.parameters().firstOrNull { param ->
- parameter.parameterIndex == param.parameterIndex
- }?.hasNullnessInfo() ?: true
- )
+ }
+ } && supers.any { superMethod ->
+ !(
+ superMethod.parameters().firstOrNull { param ->
+ parameter.parameterIndex == param.parameterIndex
+ }?.hasNullnessInfo() ?: true
+ )
}
}
diff --git a/src/test/java/com/android/tools/metalava/ApiLintTest.kt b/src/test/java/com/android/tools/metalava/ApiLintTest.kt
index 2ca80e3..41ced4d 100644
--- a/src/test/java/com/android/tools/metalava/ApiLintTest.kt
+++ b/src/test/java/com/android/tools/metalava/ApiLintTest.kt
@@ -3819,4 +3819,76 @@
)
)
}
+
+ @Test
+ fun `Nullability overrides in unbounded generics (Object to generic and back)`() {
+ check(
+ apiLint = "",
+ sourceFiles = arrayOf(
+ kotlin(
+ """
+ package test.pkg
+
+ open class SimpleArrayMap<K, V> {
+ open operator fun get(key: K): V? {
+ TODO()
+ }
+ }
+ """
+ ),
+ java(
+ """
+ package test.pkg;
+
+ import java.util.Map;
+
+ public class ArrayMap<K, V> extends SimpleArrayMap<K, V> implements Map<K, V> {
+ @Override
+ @Nullable
+ public V get(@NonNull Object key) {
+ return super.get((K) key);
+ }
+ }
+
+ """
+ )
+ )
+ )
+ }
+
+ @Test
+ fun `Nullability overrides in unbounded generics (one super method lacks nullness info)`() {
+ check(
+ apiLint = "",
+ sourceFiles = arrayOf(
+ kotlin(
+ """
+ package test.pkg
+
+ open class SimpleArrayMap<K, V> {
+ open operator fun get(key: K): V? {
+ TODO()
+ }
+ }
+ """
+ ),
+ java(
+ """
+ package test.pkg;
+
+ import java.util.Map;
+
+ public class ArrayMap<K, V> extends SimpleArrayMap<K, V> implements Map<K, V> {
+ @Override
+ @Nullable
+ public V get(@Nullable Object key) {
+ return super.get((K) key);
+ }
+ }
+
+ """
+ )
+ )
+ )
+ }
}