1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.tools.metalava.lint
18 
19 import com.android.tools.metalava.DriverTest
20 import com.android.tools.metalava.androidxNonNullSource
21 import com.android.tools.metalava.androidxNullableSource
22 import com.android.tools.metalava.cli.common.ARG_ERROR
23 import com.android.tools.metalava.cli.common.ARG_HIDE
24 import com.android.tools.metalava.cli.lint.ARG_API_LINT
25 import com.android.tools.metalava.libcoreNonNullSource
26 import com.android.tools.metalava.libcoreNullableSource
27 import com.android.tools.metalava.model.provider.Capability
28 import com.android.tools.metalava.model.testing.RequiresCapabilities
29 import com.android.tools.metalava.testing.java
30 import com.android.tools.metalava.testing.kotlin
31 import org.junit.Test
32 
33 class NullabilityLintTest : DriverTest() {
34     @Test
Test fields, parameters and returns require nullabilitynull35     fun `Test fields, parameters and returns require nullability`() {
36         check(
37             apiLint = "", // enabled
38             expectedIssues =
39                 """
40                 src/android/pkg/Foo.java:11: error: Missing nullability on parameter `name` in method `Foo` [MissingNullability]
41                 src/android/pkg/Foo.java:12: error: Missing nullability on parameter `value` in method `setBadValue` [MissingNullability]
42                 src/android/pkg/Foo.java:13: error: Missing nullability on method `getBadValue` return [MissingNullability]
43                 src/android/pkg/Foo.java:20: error: Missing nullability on parameter `duration` in method `methodMissingParamAnnotations` [MissingNullability]
44                 src/android/pkg/Foo.java:7: error: Missing nullability on field `badField` in class `class android.pkg.Foo` [MissingNullability]
45                 """,
46             expectedFail = DefaultLintErrorMessage,
47             sourceFiles =
48                 arrayOf(
49                     java(
50                         """
51                         package android.pkg;
52 
53                         import androidx.annotation.NonNull;
54                         import androidx.annotation.Nullable;
55 
56                         public class Foo<T> {
57                             public final Foo badField;
58                             @Nullable
59                             public final Foo goodField;
60 
61                             public Foo(String name, int number) { }
62                             public void setBadValue(Foo value) { }
63                             public Foo getBadValue(int number) { throw UnsupportedOperationExceptions(); }
64                             public void setGoodValue(@Nullable Foo value) { }
65                             public void setGoodIgnoredGenericValue(T value) { }
66                             @NonNull
67                             public Foo getGoodValue(int number) { throw UnsupportedOperationExceptions(); }
68 
69                             @NonNull
70                             public Foo methodMissingParamAnnotations(java.time.Duration duration) {
71                                 throw UnsupportedOperationException();
72                             }
73                         }
74                     """
75                     ),
76                     androidxNullableSource,
77                     androidxNonNullSource
78                 )
79         )
80     }
81 
82     @RequiresCapabilities(Capability.KOTLIN)
83     @Test
Test no missing nullability errors for enumsnull84     fun `Test no missing nullability errors for enums`() {
85         check(
86             apiLint = "", // enabled
87             extraArguments = arrayOf(ARG_HIDE, "Enum"),
88             sourceFiles =
89                 arrayOf(
90                     java(
91                         """
92                     package test.pkg;
93                     @SuppressWarnings("ALL")
94                     public enum Foo {
95                         A, B;
96                     }
97                     """
98                     ),
99                     kotlin(
100                         """
101                     package test.pkg
102                     enum class Language {
103                         KOTLIN,
104                         JAVA
105                     }
106                     """
107                     ),
108                 )
109         )
110     }
111 
112     @RequiresCapabilities(Capability.KOTLIN)
113     @Test
Test no missing nullability errors for kotlin constructsnull114     fun `Test no missing nullability errors for kotlin constructs`() {
115         check(
116             apiLint = "", // enabled
117             extraArguments = arrayOf(ARG_HIDE, "StaticUtils"),
118             sourceFiles =
119                 arrayOf(
120                     kotlin(
121                         """
122                     package android.pkg
123 
124                     object Bar
125 
126                     class FooBar {
127                         companion object
128                     }
129 
130                     class FooBarNamed {
131                         companion object Named
132                     }
133 
134                     class Foo {
135                         val a = 3
136                         var b: String? = null
137                     }
138                     """
139                     ),
140                 ),
141         )
142     }
143 
144     @Test
Test type variable array requires nullabilitynull145     fun `Test type variable array requires nullability`() {
146         check(
147             apiLint = "", // enabled
148             extraArguments = arrayOf(ARG_API_LINT, ARG_HIDE, "ArrayReturn"),
149             expectedIssues =
150                 """
151                 src/test/pkg/Foo.java:4: error: Missing nullability on method `badTypeVarArrayReturn` return [MissingNullability]
152             """,
153             expectedFail = DefaultLintErrorMessage,
154             sourceFiles =
155                 arrayOf(
156                     java(
157                         """
158                         package test.pkg;
159                         public class Foo<T> {
160                             public T goodTypeVarReturn() { return null; }
161                             public T[] badTypeVarArrayReturn() { return null; }
162                         }
163                     """
164                             .trimIndent()
165                     )
166                 )
167         )
168     }
169 
170     @Test
Test equals, toString, non-null constants, enums and annotation members don't require nullabilitynull171     fun `Test equals, toString, non-null constants, enums and annotation members don't require nullability`() {
172         check(
173             apiLint = "", // enabled
174             expectedIssues = "",
175             sourceFiles =
176                 arrayOf(
177                     java(
178                         """
179                         package android.pkg;
180 
181                         import android.annotation.SuppressLint;
182 
183                         public class Foo<T> {
184                             public static final String FOO_CONSTANT = "test";
185 
186                             public boolean equals(Object other) {
187                                 return other == this;
188                             }
189 
190                             public int hashCode() {
191                                 return 0;
192                             }
193 
194                             public String toString() {
195                                 return "Foo";
196                             }
197 
198                             @SuppressLint("Enum")
199                             public enum FooEnum {
200                                 FOO, BAR
201                             }
202 
203                             public @interface FooAnnotation {
204                                 String value() default "";
205                             }
206                         }
207                     """
208                     ),
209                     androidxNullableSource,
210                     androidxNonNullSource
211                 )
212         )
213     }
214 
215     @Test
216     fun `Nullability check for generic methods referencing parent type parameter`() {
217         check(
218             apiLint = "", // enabled
219             expectedIssues =
220                 """
221                 src/test/pkg/MyClass.java:14: error: Missing nullability on method `method4` return [MissingNullability]
222                 src/test/pkg/MyClass.java:14: error: Missing nullability on parameter `input` in method `method4` [MissingNullability]
223             """,
224             expectedFail = DefaultLintErrorMessage,
225             sourceFiles =
226                 arrayOf(
227                     java(
228                         """
229                     package test.pkg;
230 
231                     import androidx.annotation.NonNull;
232                     import androidx.annotation.Nullable;
233 
234                     public class MyClass extends HiddenParent<String> {
235                         public void method1() { }
236 
237                         @NonNull
238                         @Override
239                         public String method3(@Nullable String input) { return null; }
240 
241                         @Override
242                         public String method4(String input) { return null; }
243                     }
244                     """
245                     ),
246                     java(
247                         """
248                     package test.pkg;
249 
250                     class HiddenParent<T> {
251                         public T method2(T t) { }
252                         public T method3(T t) { }
253                         public T method4(T t) { }
254                     }
255                     """
256                     ),
257                     androidxNullableSource,
258                     androidxNonNullSource
259                 )
260         )
261     }
262 
263     @RequiresCapabilities(Capability.KOTLIN)
264     @Test
265     fun `No warnings about nullability on private constructor getters`() {
266         check(
267             expectedIssues = "",
268             apiLint = "",
269             sourceFiles =
270                 arrayOf(
271                     kotlin(
272                         """
273                         package test.pkg
274                         class MyClass private constructor(
275                             val myParameter: Set<Int>
276                         )
277                     """
278                     )
279                 )
280         )
281     }
282 
283     @RequiresCapabilities(Capability.KOTLIN)
284     @Test
285     fun `No error for nullability on synthetic methods`() {
286         check(
287             expectedIssues = "",
288             apiLint = "",
289             sourceFiles =
290                 arrayOf(
291                     kotlin(
292                         """
293                         package test.pkg
294                         class Foo {
295                             @JvmSynthetic
296                             fun bar(): String {}
297                         }
298                     """
299                     )
300                 )
301         )
302     }
303 
304     @Test
305     fun `Constructors return types don't require nullability`() {
306         check(
307             expectedIssues = "",
308             apiLint = "",
309             sourceFiles =
310                 arrayOf(
311                     java(
312                         """
313                         package test.pkg;
314                         import androidx.annotation.NonNull;
315                         public class Foo {
316                             // Doesn't require nullability
317                             public Foo(@NonNull String bar);
318                             // Requires nullability
319                             public @NonNull String baz(@NonNull String whatever);
320                         }
321                     """
322                     ),
323                     androidxNonNullSource
324                 )
325         )
326     }
327 
328     @Test
No nullability allowed on overrides of unannotated methods or parametersnull329     fun `No nullability allowed on overrides of unannotated methods or parameters`() {
330         check(
331             expectedIssues =
332                 """
333                 src/test/pkg/Foo.java:16: error: Invalid nullability on type java.lang.String in method `bar` return. Method override cannot use a nullable type when the corresponding type from the super method is platform-nullness. [InvalidNullabilityOverride]
334                 src/test/pkg/Foo.java:16: error: Invalid nullability on type java.lang.String in parameter `baz` in method `bar`. Parameter in method override cannot use a non-null type when the corresponding type from the super method is platform-nullness. [InvalidNullabilityOverride]
335                 src/test/pkg/Foo.java:19: error: Invalid nullability on type java.lang.String in parameter `y` in method `x`. Parameter in method override cannot use a non-null type when the corresponding type from the super method is platform-nullness. [InvalidNullabilityOverride]
336                 src/test/pkg/Foo.java:8: error: Missing nullability on method `bar` return [MissingNullability]
337                 src/test/pkg/Foo.java:8: error: Missing nullability on parameter `baz` in method `bar` [MissingNullability]
338                 src/test/pkg/Foo.java:11: error: Missing nullability on parameter `y` in method `x` [MissingNullability]
339                 """,
340             apiLint = "",
341             expectedFail = DefaultLintErrorMessage,
342             sourceFiles =
343                 arrayOf(
344                     java(
345                         """
346                         package test.pkg;
347 
348                         import androidx.annotation.NonNull;
349                         import androidx.annotation.Nullable;
350 
351                         public class Foo {
352                             // Not annotated
353                             public String bar(String baz);
354 
355                             // Partially annotated
356                             @Nullable public String x(String y);
357                         }
358                         public class Bar extends Foo {
359                             // Not allowed to mark override method Nullable if parent is not annotated
360                             // Not allowed to mark override parameter NonNull if parent is not annotated
361                             @Nullable @Override public String bar(@NonNull String baz);
362                             // It is allowed to mark the override method Nullable if the parent is Nullable.
363                             // Not allowed to mark override parameter if parent is not annotated.
364                             @Nullable @Override public String x(@NonNull String y);
365                         }
366                     """
367                     ),
368                     androidxNullableSource,
369                     androidxNonNullSource
370                 )
371         )
372     }
373 
374     @RequiresCapabilities(Capability.KOTLIN)
375     @Test
Override enforcement on kotlin sourced child classnull376     fun `Override enforcement on kotlin sourced child class`() {
377         check(
378             expectedIssues =
379                 """
380                 src/test/pkg/Bar.kt:5: error: Invalid nullability on type java.lang.String in parameter `baz` in method `bar`. Parameter in method override cannot use a non-null type when the corresponding type from the super method is platform-nullness. [InvalidNullabilityOverride]
381                 src/test/pkg/Foo.java:5: error: Missing nullability on method `bar` return [MissingNullability]
382                 src/test/pkg/Foo.java:5: error: Missing nullability on parameter `baz` in method `bar` [MissingNullability]
383                 """,
384             apiLint = "",
385             expectedFail = DefaultLintErrorMessage,
386             sourceFiles =
387                 arrayOf(
388                     java(
389                         """
390                         package test.pkg;
391 
392                         public class Foo {
393                             // Not annotated
394                             public String bar(String baz);
395                         }
396                         """
397                     ),
398                     kotlin(
399                         """
400                         package test.pkg
401                         // Not allowed to mark override method Nullable if parent is not annotated
402                         // Not allowed to mark override parameter NonNull if parent is not annotated
403                         class Bar : Foo {
404                             override fun bar(baz: String): String
405                         }
406                     """
407                     ),
408                     androidxNullableSource,
409                     androidxNonNullSource
410                 )
411         )
412     }
413 
414     @Test
Overrides of non-null methods cannot be nullablenull415     fun `Overrides of non-null methods cannot be nullable`() {
416         check(
417             expectedIssues =
418                 """
419                 src/test/pkg/Foo.java:12: error: Invalid nullability on type java.lang.String method `bar` return. Method override cannot use a nullable type when the corresponding type from the super method is non-null. [InvalidNullabilityOverride]
420                 """,
421             apiLint = "",
422             expectedFail = DefaultLintErrorMessage,
423             sourceFiles =
424                 arrayOf(
425                     java(
426                         """
427                         package test.pkg;
428 
429                         import androidx.annotation.NonNull;
430                         import androidx.annotation.Nullable;
431 
432                         public class Foo {
433                             @NonNull public String bar(@Nullable String baz);
434                         }
435 
436                         // Not allowed to mark override method Nullable if parent is nonNull
437                         public class Bar extends Foo {
438                             @Nullable @Override public String bar(@Nullable String baz);
439                         }
440                     """
441                     ),
442                     androidxNullableSource,
443                     androidxNonNullSource
444                 )
445         )
446     }
447 
448     @Test
Overrides of nullable parameters cannot be non-nullnull449     fun `Overrides of nullable parameters cannot be non-null`() {
450         check(
451             expectedIssues =
452                 """
453                 src/test/pkg/Foo.java:13: error: Invalid nullability on type java.lang.String in parameter `baz` in method `bar`. Parameter in method override cannot use a non-null type when the corresponding type from the super method is nullable. [InvalidNullabilityOverride]
454                 """,
455             apiLint = "",
456             expectedFail = DefaultLintErrorMessage,
457             sourceFiles =
458                 arrayOf(
459                     java(
460                         """
461                         package test.pkg;
462 
463                         import androidx.annotation.NonNull;
464                         import androidx.annotation.Nullable;
465 
466                         public class Foo {
467                             // Not annotated
468                             @NonNull public String bar(@Nullable String baz);
469                         }
470 
471                         // Not allowed to mark override parameter NonNull if parent is Nullable
472                         public class Bar extends Foo {
473                             @NonNull @Override public String bar(@NonNull String baz);
474                         }
475                     """
476                     ),
477                     androidxNullableSource,
478                     androidxNonNullSource
479                 )
480         )
481     }
482 
483     @RequiresCapabilities(Capability.KOTLIN)
484     @Test
Nullability overrides in unbounded generics should be allowednull485     fun `Nullability overrides in unbounded generics should be allowed`() {
486         check(
487             apiLint = "",
488             sourceFiles =
489                 arrayOf(
490                     kotlin(
491                         """
492                         package test.pkg;
493 
494                         interface Base<T> {
495                             fun method1(input: T): T
496                         }
497 
498                         class Subject1 : Base<String> {
499                             override fun method1(input: String): String {
500                                 TODO()
501                             }
502                         }
503 
504                         class Subject2 : Base<String?> {
505                             override fun method1(input: String?): String? {
506                                 TODO()
507                             }
508                         }
509                     """
510                     )
511                 )
512         )
513     }
514 
515     @Test
Invalid nullability override in function with generic parameternull516     fun `Invalid nullability override in function with generic parameter`() {
517         check(
518             apiLint = "",
519             expectedFail = DefaultLintErrorMessage,
520             expectedIssues =
521                 "src/test/pkg/StringProperty.java:5: error: Invalid nullability on type java.lang.String in parameter `arg2` in method `foo`. Parameter in method override cannot use a non-null type when the corresponding type from the super method is platform-nullness. [InvalidNullabilityOverride]",
522             sourceFiles =
523                 arrayOf(
524                     java(
525                         """
526                             package test.pkg;
527                             public abstract class Property<V> {
528                                 public abstract void foo(V arg1, @SuppressWarnings("MissingNullability") String arg2);
529                             }
530                         """
531                     ),
532                     java(
533                         """
534                             package test.pkg;
535                             import androidx.annotation.NonNull;
536                             public class StringProperty extends Property<String> {
537                                 @Override
538                                 public void foo(@NonNull String arg1, @NonNull String arg2) {}
539                             }
540                         """
541                     ),
542                     androidxNonNullSource,
543                 )
544         )
545     }
546 
547     @RequiresCapabilities(Capability.KOTLIN)
548     @Test
Nullability overrides in unbounded generics (Object to generic and back)null549     fun `Nullability overrides in unbounded generics (Object to generic and back)`() {
550         check(
551             apiLint = "",
552             expectedFail = DefaultLintErrorMessage,
553             expectedIssues =
554                 "src/test/pkg/ArrayMap.java:11: error: Invalid nullability on type java.lang.Object in parameter `key` in method `get`. Parameter in method override cannot use a non-null type when the corresponding type from the super method is nullable. [InvalidNullabilityOverride]",
555             sourceFiles =
556                 arrayOf(
557                     kotlin(
558                         """
559                         package test.pkg
560 
561                         open class SimpleArrayMap<K, V> {
562                             open operator fun get(key: K): V? {
563                                 TODO()
564                             }
565                         }
566                     """
567                     ),
568                     java(
569                         """
570                         package test.pkg;
571 
572                         import java.util.Map;
573                         import androidx.annotation.NonNull;
574                         import androidx.annotation.Nullable;
575 
576                         // The android version of [Map.get] has a @Nullable parameter
577                         public class ArrayMap<K, V> extends SimpleArrayMap<K, V> implements Map<K, V> {
578                             @Override
579                             @Nullable
580                             public V get(@NonNull Object key) {
581                                 return super.get((K) key);
582                             }
583                         }
584 
585                     """
586                     ),
587                     androidxNonNullSource,
588                     androidxNullableSource,
589                 )
590         )
591     }
592 
593     @RequiresCapabilities(Capability.KOTLIN)
594     @Test
Nullability overrides in unbounded generics (one super method lacks nullness info)null595     fun `Nullability overrides in unbounded generics (one super method lacks nullness info)`() {
596         check(
597             apiLint = "",
598             sourceFiles =
599                 arrayOf(
600                     kotlin(
601                         """
602                         package test.pkg
603 
604                         open class SimpleArrayMap<K, V> {
605                             open operator fun get(key: K): V? {
606                                 TODO()
607                             }
608                         }
609                     """
610                     ),
611                     java(
612                         """
613                         package test.pkg;
614 
615                         import java.util.Map;
616                         import androidx.annotation.Nullable;
617 
618                         // The android version of [Map.get] has a @Nullable parameter
619                         public class ArrayMap<K, V> extends SimpleArrayMap<K, V> implements Map<K, V> {
620                             @Override
621                             @Nullable
622                             public V get(@Nullable Object key) {
623                                 return super.get((K) key);
624                             }
625                         }
626                     """
627                     ),
628                     androidxNullableSource
629                 )
630         )
631     }
632 
633     @RequiresCapabilities(Capability.KOTLIN)
634     @Test
Nullability on vararg with inherited generic typenull635     fun `Nullability on vararg with inherited generic type`() {
636         check(
637             apiLint = "",
638             sourceFiles =
639                 arrayOf(
640                     java(
641                         """
642                     package androidx.collection;
643 
644                     import java.util.Collection;
645                     import java.util.HashSet;
646                     import java.util.Set;
647 
648                     public class ArraySet<E> extends HashSet<E> implements Set<E> {
649                         public ArraySet() {
650                         }
651                     }
652                         """
653                     ),
654                     kotlin(
655                         "src/main/java/androidx/collection/ArraySet.kt",
656                         """
657                     package androidx.collection
658 
659                     inline fun <T> arraySetOf(): ArraySet<T> = ArraySet()
660 
661                     fun <T> arraySetOf(vararg values: T): ArraySet<T> {
662                         val set = ArraySet<T>(values.size)
663                         for (value in values) {
664                             set.add(value)
665                         }
666                         return set
667                     }
668                     """
669                     )
670                 )
671         )
672     }
673 
674     @Test
Missing inner nullabilitynull675     fun `Missing inner nullability`() {
676         check(
677             apiLint = "",
678             extraArguments = arrayOf(ARG_ERROR, "MissingInnerNullability"),
679             expectedFail = DefaultLintErrorMessage,
680             expectedIssues =
681                 """
682                     src/test/pkg/Foo.java:5: error: Missing nullability on method `getArray` return [MissingNullability]
683                     src/test/pkg/Foo.java:5: error: Missing nullability on inner type java.lang.String in method `getArray` return [MissingInnerNullability]
684                     src/test/pkg/Foo.java:6: error: Missing nullability on method `getMap` return [MissingNullability]
685                     src/test/pkg/Foo.java:6: error: Missing nullability on inner type java.lang.Number in method `getMap` return [MissingInnerNullability]
686                     src/test/pkg/Foo.java:6: error: Missing nullability on inner type java.lang.String in method `getMap` return [MissingInnerNullability]
687                     src/test/pkg/Foo.java:7: error: Missing nullability on method `getWildcardMap` return [MissingNullability]
688                     src/test/pkg/Foo.java:7: error: Missing nullability on inner type java.lang.Number in method `getWildcardMap` return [MissingInnerNullability]
689                     src/test/pkg/Foo.java:7: error: Missing nullability on inner type java.lang.String in method `getWildcardMap` return [MissingInnerNullability]
690                 """,
691             sourceFiles =
692                 arrayOf(
693                     java(
694                         """
695                             package test.pkg;
696                             import java.util.List;
697                             import java.util.Map;
698                             public class Foo {
699                                 public String[] getArray() { return null; }
700                                 public Map<Number, String> getMap() { return null; }
701                                 public Map<? extends Number, ? super String> getWildcardMap() { return null; }
702                             }
703                         """
704                     )
705                 ),
706         )
707     }
708 
709     @Test
Test inner type nullness overrides of defined nullnessnull710     fun `Test inner type nullness overrides of defined nullness`() {
711         check(
712             apiLint = "",
713             extraArguments = arrayOf(ARG_HIDE, "NullableCollectionElement"),
714             expectedFail = DefaultLintErrorMessage,
715             expectedIssues =
716                 """
717                     src/test/pkg/Foo.java:7: error: Invalid nullability on type java.lang.String method `foo` return. Method override cannot use a nullable type when the corresponding type from the super method is non-null. [InvalidNullabilityOverride]
718                     src/test/pkg/Foo.java:7: error: Invalid nullability on type java.lang.String in parameter `arg` in method `foo`. Parameter in method override cannot use a non-null type when the corresponding type from the super method is nullable. [InvalidNullabilityOverride]
719                 """,
720             sourceFiles =
721                 arrayOf(
722                     java(
723                         """
724                             package test.pkg;
725                             import java.util.List;
726                             import libcore.util.NonNull;
727                             import libcore.util.Nullable;
728                             public class Superclass {
729                                 public @NonNull String @NonNull [] foo(@NonNull List<@Nullable String> arg) { return null; }
730                             }
731                         """
732                     ),
733                     java(
734                         """
735                             package test.pkg;
736                             import java.util.List;
737                             import libcore.util.NonNull;
738                             import libcore.util.Nullable;
739                             public class Foo extends Superclass {
740                                 @Override
741                                 public @Nullable String @NonNull [] foo(@NonNull List<@NonNull String> arg) { return null; }
742                             }
743                         """
744                     ),
745                     libcoreNonNullSource,
746                     libcoreNullableSource,
747                 )
748         )
749     }
750 
751     @Test
Test inner type nullness overrides of platform nullnessnull752     fun `Test inner type nullness overrides of platform nullness`() {
753         // TODO (b/344859664): this case is ignored for now
754         check(
755             apiLint = "",
756             extraArguments = arrayOf(ARG_HIDE, "NullableCollectionElement"),
757             sourceFiles =
758                 arrayOf(
759                     java(
760                         """
761                             package test.pkg;
762                             import libcore.util.NonNull;
763                             import libcore.util.Nullable;
764                             public class Superclass {
765                                 public String @NonNull [] foo(@NonNull List<String> arg) { return null; }
766                             }
767                         """
768                     ),
769                     java(
770                         """
771                             package test.pkg;
772                             import libcore.util.NonNull;
773                             import libcore.util.Nullable;
774                             public class Foo extends Superclass {
775                                 @Override
776                                 public @Nullable String @NonNull [] foo(@NonNull List<@NonNull String> arg) { return null; }
777                             }
778                         """
779                     ),
780                     libcoreNonNullSource,
781                     libcoreNullableSource,
782                 )
783         )
784     }
785 }
786