Merge "Do not enforce nullability on generic types."
diff --git a/src/main/java/com/android/tools/metalava/ApiLint.kt b/src/main/java/com/android/tools/metalava/ApiLint.kt
index 106d9d6..a82e159 100644
--- a/src/main/java/com/android/tools/metalava/ApiLint.kt
+++ b/src/main/java/com/android/tools/metalava/ApiLint.kt
@@ -1780,6 +1780,13 @@
private fun checkHasNullability(item: Item) {
if (item.requiresNullnessInfo() && !item.hasNullnessInfo()) {
+ val type = item.type()
+ if (type != null && type.isTypeParameter()) {
+ // Generic types should have declarations of nullability set at the site of where
+ // the type is set, so that for Foo<T>, T does not need to specify nullability, but
+ // for Foo<Bar>, Bar does.
+ return // Do not enforce nullability for generics
+ }
val where = when (item) {
is ParameterItem -> "parameter `${item.name()}` in method `${item.parent()?.name()}`"
is FieldItem -> "field `${item.name()}` in class `${item.parent()}`"
diff --git a/src/main/java/com/android/tools/metalava/model/TypeItem.kt b/src/main/java/com/android/tools/metalava/model/TypeItem.kt
index ca9266c..e7dbd6d 100644
--- a/src/main/java/com/android/tools/metalava/model/TypeItem.kt
+++ b/src/main/java/com/android/tools/metalava/model/TypeItem.kt
@@ -162,6 +162,11 @@
fun asTypeParameter(context: MemberItem? = null): TypeParameterItem?
/**
+ * Whether this type is a type parameter.
+ */
+ fun isTypeParameter(context: MemberItem? = null): Boolean = asTypeParameter(context) != null
+
+ /**
* Mark nullness annotations in the type as recent.
* TODO: This isn't very clean; we should model individual annotations.
*/
diff --git a/src/test/java/com/android/tools/metalava/ApiLintTest.kt b/src/test/java/com/android/tools/metalava/ApiLintTest.kt
index 626c2e9..02a38c3 100644
--- a/src/test/java/com/android/tools/metalava/ApiLintTest.kt
+++ b/src/test/java/com/android/tools/metalava/ApiLintTest.kt
@@ -2258,7 +2258,7 @@
src/android/pkg/Foo.java:11: error: Missing nullability on parameter `name` in method `Foo` [MissingNullability]
src/android/pkg/Foo.java:12: error: Missing nullability on parameter `value` in method `setBadValue` [MissingNullability]
src/android/pkg/Foo.java:13: error: Missing nullability on method `getBadValue` return [MissingNullability]
- src/android/pkg/Foo.java:19: error: Missing nullability on parameter `duration` in method `methodMissingParamAnnotations` [MissingNullability]
+ src/android/pkg/Foo.java:20: error: Missing nullability on parameter `duration` in method `methodMissingParamAnnotations` [MissingNullability]
src/android/pkg/Foo.java:7: error: Missing nullability on field `badField` in class `class android.pkg.Foo` [MissingNullability]
""",
sourceFiles = *arrayOf(
@@ -2269,7 +2269,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
- public class Foo {
+ public class Foo<T> {
public Foo badField;
@Nullable
public Foo goodField;
@@ -2278,9 +2278,10 @@
public void setBadValue(Foo value) { }
public Foo getBadValue(int number) { throw UnsupportedOperationExceptions(); }
public void setGoodValue(@Nullable Foo value) { }
+ public void setGoodIgnoredGenericValue(T value) { }
@NonNull
public Foo getGoodValue(int number) { throw UnsupportedOperationExceptions(); }
-
+
@NonNull
public Foo methodMissingParamAnnotations(java.time.Duration duration) {
throw UnsupportedOperationException();