1 /*
2  * Copyright (C) 2017 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 @file:Suppress("ALL")
18 
19 package com.android.tools.metalava
20 
21 import com.android.tools.lint.checks.infrastructure.TestFiles.base64gzip
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.common.ARG_WARNING
25 import com.android.tools.metalava.lint.DefaultLintErrorMessage
26 import com.android.tools.metalava.model.provider.Capability
27 import com.android.tools.metalava.model.testing.RequiresCapabilities
28 import com.android.tools.metalava.model.text.FileFormat
29 import com.android.tools.metalava.model.text.FileFormat.OverloadedMethodOrder
30 import com.android.tools.metalava.testing.java
31 import com.android.tools.metalava.testing.kotlin
32 import org.junit.Test
33 
34 class ApiFileTest : DriverTest() {
35     /*
36       Conditions to test:
37       - test all the error scenarios found in the notStrippable case!
38       - split up test into many individual test cases
39       - try referencing a class from an annotation!
40       - test having a throws list where some exceptions are hidden but extend
41         public exceptions: do we map over to the referenced ones?
42 
43       - test type reference from all the possible places -- in type signatures - interfaces,
44         extends, throws, type bounds, etc.
45       - method which overrides @hide method: should appear in subclass (test chain
46         of two nested too)
47       - BluetoothGattCharacteristic.java#describeContents: Was marked @hide,
48         but is unhidden because it extends a public interface method
49       - package javadoc (also make sure merging both!, e.g. try having @hide in each)
50       - StopWatchMap -- inner class with @hide marks all top levels!
51       - Test field inlining: should I include fields from an interface, if that
52         interface was implemented by the parent class (and therefore appears there too?)
53         What if the superclass is abstract?
54       - Exposing package private classes. Test that I only do this for package private
55         classes, NOT Those marked @hide (is that, having @hide on a used type, illegal?)
56       - Test error handling (invalid @hide combinations))
57       - Consider what happens if we promote a package private class (because it's
58         extended by a public class), and then we restore its public members; the
59         override logic there isn't quite right. We've duplicated the significant-override
60         code to not skip private members, but that could change semantics. This isn't
61         ideal; instead we should now mark this class as public, and re-run the analysis
62         again (with the new hidden state for this class).
63       - compilation unit sorting - top level classes out of order
64       - Massive classes such as android.R.java? Maybe do synthetic test.
65       - HttpResponseCache implemented a public OkHttp interface, but the sole implementation
66         method was marked @hide, so the method doesn't show up. Is that some other rule --
67         that we skip interfaces if their implementation methods are marked @hide?
68       - Test recursive package filtering.
69     */
70 
71     @RequiresCapabilities(Capability.KOTLIN)
72     @Test
Kotlin language levelnull73     fun `Kotlin language level`() {
74         // static method in interface is not overridable.
75         // See https://kotlinlang.org/docs/reference/whatsnew13.html
76         check(
77             format = FileFormat.V2,
78             sourceFiles =
79                 arrayOf(
80                     kotlin(
81                         """
82                     package test.pkg
83                     interface Foo {
84                         companion object {
85                             @JvmField
86                             const val answer: Int = 42
87                             @JvmStatic
88                             fun sayHello() {
89                                 println("Hello, world!")
90                             }
91                         }
92                     }
93                     """
94                     )
95                 ),
96             api =
97                 """
98                 package test.pkg {
99                   public interface Foo {
100                     method public static void sayHello();
101                     field @NonNull public static final test.pkg.Foo.Companion Companion;
102                     field public static final int answer = 42; // 0x2a
103                   }
104                   public static final class Foo.Companion {
105                     method public void sayHello();
106                   }
107                 }
108                 """,
109             // The above source uses 1.3 features, though UAST currently
110             // seems to still treat it as 1.3 despite being passed 1.2
111             extraArguments = arrayOf(ARG_KOTLIN_SOURCE, "1.2")
112         )
113     }
114 
115     @Test
Basic class signature extractionnull116     fun `Basic class signature extraction`() {
117         // Basic class; also checks that default constructor is made explicit
118         check(
119             sourceFiles =
120                 arrayOf(
121                     java(
122                         """
123                     package test.pkg;
124                     public class Foo {
125                     }
126                     """
127                     )
128                 ),
129             api =
130                 """
131                     package test.pkg {
132                       public class Foo {
133                         ctor public Foo();
134                       }
135                     }
136                     """
137         )
138     }
139 
140     @Test
Parameter Names in Javanull141     fun `Parameter Names in Java`() {
142         // Java code which explicitly specifies parameter names
143         check(
144             sourceFiles =
145                 arrayOf(
146                     java(
147                         """
148                     package test.pkg;
149                     import androidx.annotation.ParameterName;
150 
151                     public class Foo {
152                         public void foo(int javaParameter1, @ParameterName("publicParameterName") int javaParameter2) {
153                         }
154                     }
155                     """
156                     ),
157                     supportParameterName
158                 ),
159             api =
160                 """
161                     package test.pkg {
162                       public class Foo {
163                         ctor public Foo();
164                         method public void foo(int, int publicParameterName);
165                       }
166                     }
167                  """,
168             extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation")
169         )
170     }
171 
172     @Test
Default Values Names in Javanull173     fun `Default Values Names in Java`() {
174         // Java code which explicitly specifies parameter names
175         check(
176             format = FileFormat.V3,
177             sourceFiles =
178                 arrayOf(
179                     java(
180                         """
181                     package test.pkg;
182                     import androidx.annotation.DefaultValue;
183 
184                     public class Foo {
185                         public void foo(
186                             @DefaultValue("null") String prefix,
187                             @DefaultValue("\"Hello World\"") String greeting,
188                             @DefaultValue("42") int meaning) {
189                         }
190                     }
191                     """
192                     ),
193                     supportDefaultValue
194                 ),
195             api =
196                 """
197                 // Signature format: 3.0
198                 package test.pkg {
199                   public class Foo {
200                     ctor public Foo();
201                     method public void foo(String! = null, String! = "Hello World", int = 42);
202                   }
203                 }
204                  """,
205             extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation")
206         )
207     }
208 
209     @RequiresCapabilities(Capability.KOTLIN)
210     @Test
Default Values and Names in Kotlinnull211     fun `Default Values and Names in Kotlin`() {
212         // Kotlin code which explicitly specifies parameter names
213         check(
214             format = FileFormat.V3,
215             sourceFiles =
216                 arrayOf(
217                     kotlin(
218                         """
219                     package test.pkg
220                     import some.other.pkg.Constants.Misc.SIZE
221                     import android.graphics.Bitmap
222                     import android.view.View
223 
224                     class Foo {
225                         fun method1(myInt: Int = 42,
226                             myInt2: Int? = null,
227                             myByte: Int = 2 * 21,
228                             str: String = "hello " + "world",
229                             vararg args: String) { }
230 
231                         fun method2(myInt: Int, myInt2: Int = (2*myInt) * SIZE) { }
232 
233                         fun method3(str: String, myInt: Int, myInt2: Int = double(myInt) + str.length) { }
234 
235                         fun emptyLambda(sizeOf: () -> Unit = {  }) {}
236 
237                         fun View.drawToBitmap(config: Bitmap.Config = Bitmap.Config.ARGB_8888): Bitmap? = null
238 
239                         companion object {
240                             fun double(myInt: Int) = 2 * myInt
241                             fun print(foo: Foo = Foo()) { println(foo) }
242                         }
243                     }
244                     """
245                     ),
246                     java(
247                         """
248                     package some.other.pkg;
249                     public class Constants {
250                         public static class Misc {
251                             public static final int SIZE = 5;
252                         }
253                     }
254                     """
255                     )
256                 ),
257             api =
258                 """
259                 // Signature format: 3.0
260                 package test.pkg {
261                   public final class Foo {
262                     ctor public Foo();
263                     method public android.graphics.Bitmap? drawToBitmap(android.view.View, android.graphics.Bitmap.Config config = android.graphics.Bitmap.Config.ARGB_8888);
264                     method public void emptyLambda(kotlin.jvm.functions.Function0<kotlin.Unit> sizeOf = {});
265                     method public void method1(int myInt = 42, Integer? myInt2 = null, int myByte = 42, String str = "hello world", java.lang.String... args);
266                     method public void method2(int myInt, int myInt2 = (2 * myInt) * some.other.pkg.Constants.Misc.SIZE);
267                     method public void method3(String str, int myInt, int myInt2 = double(myInt) + str.length);
268                     field public static final test.pkg.Foo.Companion Companion;
269                   }
270                   public static final class Foo.Companion {
271                     method public int double(int myInt);
272                     method public void print(test.pkg.Foo foo = test.pkg.Foo());
273                   }
274                 }
275                 """,
276             extraArguments =
277                 arrayOf(
278                     ARG_HIDE_PACKAGE,
279                     "androidx.annotation",
280                     ARG_HIDE_PACKAGE,
281                     "some.other.pkg"
282                 ),
283         )
284     }
285 
286     @RequiresCapabilities(Capability.KOTLIN)
287     @Test
Default Values in Kotlin for expressionsnull288     fun `Default Values in Kotlin for expressions`() {
289         // Testing trickier default values; regression test for problem
290         // observed in androidx.core.util with LruCache
291         check(
292             format = FileFormat.V3,
293             sourceFiles =
294                 arrayOf(
295                     kotlin(
296                         """
297                     package androidx.core.util
298 
299                     import android.util.LruCache
300 
301                     inline fun <K : Any, V : Any> lruCache(
302                         maxSize: Int,
303                         crossinline sizeOf: (key: K, value: V) -> Int = { _, _ -> 1 },
304                         @Suppress("USELESS_CAST") // https://youtrack.jetbrains.com/issue/KT-21946
305                         crossinline create: (key: K) -> V? = { null as V? },
306                         crossinline onEntryRemoved: (evicted: Boolean, key: K, oldValue: V, newValue: V?) -> Unit =
307                             { _, _, _, _ -> }
308                     ): LruCache<K, V> {
309                         return object : LruCache<K, V>(maxSize) {
310                             override fun sizeOf(key: K, value: V) = sizeOf(key, value)
311                             override fun create(key: K) = create(key)
312                             override fun entryRemoved(evicted: Boolean, key: K, oldValue: V, newValue: V?) {
313                                 onEntryRemoved(evicted, key, oldValue, newValue)
314                             }
315                         }
316                     }
317                     """
318                     ),
319                     java(
320                         """
321                     package androidx.collection;
322 
323                     import androidx.annotation.NonNull;
324                     import androidx.annotation.Nullable;
325 
326                     import java.util.LinkedHashMap;
327                     import java.util.Locale;
328                     import java.util.Map;
329 
330                     public class LruCache<K, V> {
331                         @Nullable
332                         protected V create(@NonNull K key) {
333                             return null;
334                         }
335 
336                         protected int sizeOf(@NonNull K key, @NonNull V value) {
337                             return 1;
338                         }
339 
340                         protected void entryRemoved(boolean evicted, @NonNull K key, @NonNull V oldValue,
341                                 @Nullable V newValue) {
342                         }
343                     }
344                     """
345                     ),
346                     androidxNullableSource,
347                     androidxNonNullSource
348                 ),
349             api =
350                 """
351                 // Signature format: 3.0
352                 package androidx.core.util {
353                   public final class TestKt {
354                     method public static inline <K, V> android.util.LruCache<K,V> lruCache(int maxSize, kotlin.jvm.functions.Function2<? super K,? super V,java.lang.Integer> sizeOf = { _, _ -> return 1 }, kotlin.jvm.functions.Function1<? super K,? extends V?> create = { it -> return null as V }, kotlin.jvm.functions.Function4<? super java.lang.Boolean,? super K,? super V,? super V?,kotlin.Unit> onEntryRemoved = { _, _, _, _ ->  });
355                   }
356                 }
357                 """,
358             extraArguments =
359                 arrayOf(
360                     ARG_HIDE_PACKAGE,
361                     "androidx.annotation",
362                     ARG_HIDE_PACKAGE,
363                     "androidx.collection"
364                 ),
365         )
366     }
367 
368     @RequiresCapabilities(Capability.KOTLIN)
369     @Test
Basic Kotlin classnull370     fun `Basic Kotlin class`() {
371         check(
372             format = FileFormat.V2,
373             sourceFiles =
374                 arrayOf(
375                     kotlin(
376                         """
377                     package test.pkg
378                     class Kotlin(val property1: String = "Default Value", arg2: Int) : Parent() {
379                         override fun method() = "Hello World"
380                         fun otherMethod(ok: Boolean, times: Int) {
381                         }
382 
383                         var property2: String? = null
384 
385                         private var someField = 42
386                         @JvmField
387                         var someField2 = 42
388 
389                         internal var myHiddenVar = false
390                         internal fun myHiddenMethod() { }
391                         internal data class myHiddenClass(): Unit
392 
393                         companion object {
394                             const val MY_CONST = 42
395                         }
396                     }
397 
398                     //@get:RequiresApi(26)
399                     inline val @receiver:String Long.isSrgb get() = true
400                     inline val /*@receiver:ColorInt*/ Int.red get() = 0
401                     inline operator fun String.component1() = ""
402 
403                     open class Parent {
404                         open fun method(): String? = null
405                         open fun method2(value: Boolean, value: Boolean?): String? = null
406                         open fun method3(value: Int?, value2: Int): Int = null
407                     }
408                     """
409                     )
410                 ),
411             api =
412                 """
413                 package test.pkg {
414                   public final class Kotlin extends test.pkg.Parent {
415                     ctor public Kotlin(@NonNull String property1 = "Default Value", int arg2);
416                     method @NonNull public String getProperty1();
417                     method @Nullable public String getProperty2();
418                     method public void otherMethod(boolean ok, int times);
419                     method public void setProperty2(@Nullable String);
420                     property @NonNull public final String property1;
421                     property @Nullable public final String property2;
422                     field @NonNull public static final test.pkg.Kotlin.Companion Companion;
423                     field public static final int MY_CONST = 42; // 0x2a
424                     field public int someField2;
425                   }
426                   public static final class Kotlin.Companion {
427                   }
428                   public final class KotlinKt {
429                     method @NonNull public static inline operator String component1(@NonNull String);
430                     method public static inline int getRed(int);
431                     method public static inline boolean isSrgb(long);
432                   }
433                   public class Parent {
434                     ctor public Parent();
435                     method @Nullable public String method();
436                     method @Nullable public String method2(boolean value, @Nullable Boolean value);
437                     method public int method3(@Nullable Integer value, int value2);
438                   }
439                 }
440                 """
441         )
442     }
443 
444     @RequiresCapabilities(Capability.KOTLIN)
445     @Test
Kotlin Reified Methods 2null446     fun `Kotlin Reified Methods 2`() {
447         check(
448             format = FileFormat.V2,
449             sourceFiles =
450                 arrayOf(
451                     kotlin(
452                         """
453                     @file:Suppress("All", "RedundantVisibilityModifier")
454 
455                     package test.pkg
456                     import kotlin.collections.List
457 
458                     inline fun <T> inlineNoReified(t: T): T { return t }
459                     inline fun <reified T> inlineReified(t: T) { }
460                     private inline fun <reified T> privateInlineReified(t: T) { } // hide
461                     internal inline fun <reified T> internalInlineReified(t: T) { } // hide
462                     public inline fun <reified T> publicInlineReified(t: T): T { return t }
463                     inline fun <reified T> T.inlineReifiedExtension(t: T) { this }
464                     public inline fun <reified T> inlineReifiedTakesAndReturnsArray(t: Array<T>): Array<T> { return t }
465                     public inline fun <reified T> inlineReifiedTakesAndReturnsList(t: List<T>): List<T> { return t }
466                     """
467                     )
468                 ),
469             api =
470                 """
471                 package test.pkg {
472                   public final class TestKt {
473                     method public static inline <T> T inlineNoReified(T t);
474                     method public static inline <reified T> void inlineReified(T t);
475                     method public static inline <reified T> void inlineReifiedExtension(T, T t);
476                     method @NonNull public static inline <reified T> T[] inlineReifiedTakesAndReturnsArray(@NonNull T[] t);
477                     method @NonNull public static inline <reified T> java.util.List<T> inlineReifiedTakesAndReturnsList(@NonNull java.util.List<? extends T> t);
478                     method public static inline <reified T> T publicInlineReified(T t);
479                   }
480                 }
481                 """
482         )
483     }
484 
485     @RequiresCapabilities(Capability.KOTLIN)
486     @Test
Suspend functionsnull487     fun `Suspend functions`() {
488         check(
489             format = FileFormat.V2,
490             sourceFiles =
491                 arrayOf(
492                     kotlin(
493                         """
494                     package test.pkg
495                     suspend inline fun hello(foo: Int) { }
496                     suspend fun String.hello(foo: Int = 0) { }
497                     suspend fun helloTwoContinuations(myContinuation: kotlin.coroutines.Continuation<Any>) { }
498                     internal suspend fun internalHello() { }
499                     private suspend fun privateHello() { }
500                     """
501                     )
502                 ),
503             api =
504                 """
505                 package test.pkg {
506                   public final class TestKt {
507                     method @Nullable public static suspend inline Object hello(int foo, @NonNull kotlin.coroutines.Continuation<? super kotlin.Unit>);
508                     method @Nullable public static suspend Object hello(@NonNull String, int foo = 0, @NonNull kotlin.coroutines.Continuation<? super kotlin.Unit>);
509                     method @Nullable public static suspend Object helloTwoContinuations(@NonNull kotlin.coroutines.Continuation<java.lang.Object> myContinuation, @NonNull kotlin.coroutines.Continuation<? super kotlin.Unit>);
510                   }
511                 }
512                 """
513         )
514     }
515 
516     @RequiresCapabilities(Capability.KOTLIN)
517     @Test
Var properties with private settersnull518     fun `Var properties with private setters`() {
519         check(
520             format = FileFormat.V3,
521             sourceFiles =
522                 arrayOf(
523                     kotlin(
524                         """
525                     package test.pkg
526                     class MyClass {
527                         // This property should have no public setter
528                         var readOnlyVar = false
529                             internal set
530                         // This property should have no public setter
531                         public var readOnlyVarWithPublicModifer = false
532                             internal set
533                     }
534                     """
535                     )
536                 ),
537             api =
538                 """
539                 // Signature format: 3.0
540                 package test.pkg {
541                   public final class MyClass {
542                     ctor public MyClass();
543                     method public boolean getReadOnlyVar();
544                     method public boolean getReadOnlyVarWithPublicModifer();
545                     property public final boolean readOnlyVar;
546                     property public final boolean readOnlyVarWithPublicModifer;
547                   }
548                 }
549                 """
550         )
551     }
552 
553     @RequiresCapabilities(Capability.KOTLIN)
554     @Test
Kotlin Genericsnull555     fun `Kotlin Generics`() {
556         check(
557             format = FileFormat.V3,
558             sourceFiles =
559                 arrayOf(
560                     kotlin(
561                         """
562                     package test.pkg
563                     class Bar
564                     class Type<in T> {
565                         fun foo(param: Type<Bar>) {
566                         }
567                     }
568                     """
569                     )
570                 ),
571             api =
572                 """
573                 // Signature format: 3.0
574                 package test.pkg {
575                   public final class Bar {
576                     ctor public Bar();
577                   }
578                   public final class Type<T> {
579                     ctor public Type();
580                     method public void foo(test.pkg.Type<? super test.pkg.Bar> param);
581                   }
582                 }
583                 """
584         )
585     }
586 
587     @RequiresCapabilities(Capability.KOTLIN)
588     @Test
Nullness in reified signaturesnull589     fun `Nullness in reified signatures`() {
590         check(
591             sourceFiles =
592                 arrayOf(
593                     kotlin(
594                         "src/test/pkg/test.kt",
595                         """
596                     package test.pkg
597 
598                     import androidx.annotation.UiThread
599                     import test.pkg2.NavArgs
600                     import test.pkg2.NavArgsLazy
601                     import test.pkg2.Fragment
602                     import test.pkg2.Bundle
603 
604                     @UiThread
605                     inline fun <reified Args : NavArgs> Fragment.navArgs() = NavArgsLazy(Args::class) {
606                         throw IllegalStateException("Fragment $this has null arguments")
607                     }
608                     """
609                     ),
610                     kotlin(
611                         """
612                     package test.pkg2
613 
614                     import kotlin.reflect.KClass
615 
616                     interface NavArgs
617                     class Fragment
618                     class Bundle
619                     class NavArgsLazy<Args : NavArgs>(
620                         private val navArgsClass: KClass<Args>,
621                         private val argumentProducer: () -> Bundle
622                     )
623                     """
624                     ),
625                     uiThreadSource
626                 ),
627             api =
628                 """
629                 // Signature format: 3.0
630                 package test.pkg {
631                   public final class TestKt {
632                     method @UiThread public static inline <reified Args extends test.pkg2.NavArgs> test.pkg2.NavArgsLazy<Args> navArgs(test.pkg2.Fragment);
633                   }
634                 }
635                 """,
636             format = FileFormat.V3,
637             extraArguments =
638                 arrayOf(
639                     ARG_HIDE_PACKAGE,
640                     "androidx.annotation",
641                     ARG_HIDE_PACKAGE,
642                     "test.pkg2",
643                     ARG_HIDE,
644                     "ReferencesHidden",
645                     ARG_HIDE,
646                     "UnavailableSymbol",
647                     ARG_HIDE,
648                     "HiddenTypeParameter",
649                     ARG_HIDE,
650                     "HiddenSuperclass"
651                 )
652         )
653     }
654 
655     @RequiresCapabilities(Capability.KOTLIN)
656     @Test
Nullness in varargsnull657     fun `Nullness in varargs`() {
658         check(
659             sourceFiles =
660                 arrayOf(
661                     java(
662                         """
663                     package androidx.collection;
664 
665                     import java.util.Collection;
666                     import java.util.HashMap;
667                     import java.util.Map;
668 
669                     public class ArrayMap<K, V> extends HashMap<K, V> implements Map<K, V> {
670                         public ArrayMap() {
671                         }
672                     }
673                     """
674                     ),
675                     java(
676                         """
677                     package androidx.collection;
678 
679                     import java.util.Collection;
680                     import java.util.HashSet;
681                     import java.util.Set;
682 
683                     public class ArraySet<E> extends HashSet<E> implements Set<E> {
684                         public ArraySet() {
685                         }
686                     }
687                     """
688                     ),
689                     java(
690                         """
691                     package androidx.core.app;
692 
693                     import java.util.ArrayList;
694                     import java.util.List;
695 
696                     import androidx.annotation.NonNull;
697                     import androidx.annotation.Nullable;
698 
699                     public class ActivityOptionsCompat {
700                         private ActivityOptionsCompat() {
701                         }
702                         @NonNull
703                         public static List<String> javaListOf(String... sharedElements) {
704                             return new ArrayList<String>();
705                         }
706                         @Nullable
707                         public static List<String> javaListOfNullable(String... sharedElements) {
708                             return null;
709                         }
710 
711                     }
712                     """
713                     ),
714                     kotlin(
715                         "src/main/java/androidx/collection/ArrayMap.kt",
716                         """
717                     package androidx.collection
718 
719                     inline fun <K, V> arrayMapOf(): ArrayMap<K, V> = ArrayMap()
720 
721                     fun <K, V> arrayMapOf(vararg pairs: Pair<K, V>): ArrayMap<K, V> {
722                         val map = ArrayMap<K, V>(pairs.size)
723                         for (pair in pairs) {
724                             map[pair.first] = pair.second
725                         }
726                         return map
727                     }
728                     fun <K, V> arrayMapOfNullable(vararg pairs: Pair<K, V>?): ArrayMap<K, V>? {
729                         return null
730                     }
731                     """
732                     ),
733                     kotlin(
734                         "src/main/java/androidx/collection/ArraySet.kt",
735                         """
736                     package androidx.collection
737 
738                     inline fun <T> arraySetOf(): ArraySet<T> = ArraySet()
739 
740                     fun <T> arraySetOf(vararg values: T): ArraySet<T> {
741                         val set = ArraySet<T>(values.size)
742                         for (value in values) {
743                             set.add(value)
744                         }
745                         return set
746                     }
747 
748                     fun <T> arraySetOfNullable(vararg values: T?): ArraySet<T>? {
749                         return null
750                     }
751                     """
752                     ),
753                     androidxNonNullSource,
754                     androidxNullableSource
755                 ),
756             api =
757                 """
758                 // Signature format: 3.0
759                 package androidx.collection {
760                   public class ArrayMap<K, V> extends java.util.HashMap<K!,V!> implements java.util.Map<K!,V!> {
761                     ctor public ArrayMap();
762                   }
763                   public final class ArrayMapKt {
764                     method public static inline <K, V> androidx.collection.ArrayMap<K,V> arrayMapOf();
765                     method public static <K, V> androidx.collection.ArrayMap<K,V> arrayMapOf(kotlin.Pair<? extends K,? extends V>... pairs);
766                     method public static <K, V> androidx.collection.ArrayMap<K,V>? arrayMapOfNullable(kotlin.Pair<? extends K,? extends V>?... pairs);
767                   }
768                   public class ArraySet<E> extends java.util.HashSet<E!> implements java.util.Set<E!> {
769                     ctor public ArraySet();
770                   }
771                   public final class ArraySetKt {
772                     method public static inline <T> androidx.collection.ArraySet<T> arraySetOf();
773                     method public static <T> androidx.collection.ArraySet<T> arraySetOf(T... values);
774                     method public static <T> androidx.collection.ArraySet<T>? arraySetOfNullable(T?... values);
775                   }
776                 }
777                 package androidx.core.app {
778                   public class ActivityOptionsCompat {
779                     method public static java.util.List<java.lang.String!> javaListOf(java.lang.String!...!);
780                     method public static java.util.List<java.lang.String!>? javaListOfNullable(java.lang.String!...!);
781                   }
782                 }
783                 """,
784             format = FileFormat.V3,
785             extraArguments =
786                 arrayOf(
787                     ARG_HIDE_PACKAGE,
788                     "androidx.annotation",
789                     ARG_HIDE,
790                     "ReferencesHidden",
791                     ARG_HIDE,
792                     "UnavailableSymbol",
793                     ARG_HIDE,
794                     "HiddenTypeParameter"
795                 )
796         )
797     }
798 
799     @RequiresCapabilities(Capability.KOTLIN)
800     @Test
Nullness in type parametersnull801     fun `Nullness in type parameters`() {
802         check(
803             sourceFiles =
804                 arrayOf(
805                     kotlin(
806                         """
807                     package test.pkg
808                     class NonNullUpperBound<T : Any>(ctorParam: T) {
809                         fun explicitNullable(e: T?): T? = e
810                         fun inheritedNullability(i: T): T = i
811                     }
812 
813                     class NullableUpperBound<T : Any?>(ctorParam: T) {
814                         fun explicitNullable(e: T?): T? = e
815                         fun inheritedNullability(i: T): T = i
816                     }
817 
818                     class UnspecifiedUpperBound<T>(ctorParam: T) {
819                         fun explicitNullable(e: T?): T? = e
820                         fun inheritedNullability(i: T): T = i
821                     }
822 
823                     fun <T : Any> topLevelNonNullUpperBoundExplicitNullable(t: T?) = t
824                     fun <T : Any> topLevelNonNullUpperBoundInherited(t: T) = t
825 
826                     fun <T : Any?> topLevelNullableUpperBoundExplicitNullable(t: T?) = t
827                     fun <T : Any?> topLevelNullableUpperBoundInherited(t: T) = t
828 
829                     fun <T> topLevelUnspecifiedUpperBoundExplicitNullable(t: T?) = t
830                     fun <T> topLevelUnspecifiedUpperBoundInherited(t: T) = t
831                     """
832                     )
833                 ),
834             api =
835                 """
836                 package test.pkg {
837                   public final class NonNullUpperBound<T> {
838                     ctor public NonNullUpperBound(T ctorParam);
839                     method public T? explicitNullable(T? e);
840                     method public T inheritedNullability(T i);
841                   }
842                   public final class NonNullUpperBoundKt {
843                     method public static <T> T? topLevelNonNullUpperBoundExplicitNullable(T? t);
844                     method public static <T> T topLevelNonNullUpperBoundInherited(T t);
845                     method public static <T> T? topLevelNullableUpperBoundExplicitNullable(T? t);
846                     method public static <T> T topLevelNullableUpperBoundInherited(T t);
847                     method public static <T> T? topLevelUnspecifiedUpperBoundExplicitNullable(T? t);
848                     method public static <T> T topLevelUnspecifiedUpperBoundInherited(T t);
849                   }
850                   public final class NullableUpperBound<T> {
851                     ctor public NullableUpperBound(T ctorParam);
852                     method public T? explicitNullable(T? e);
853                     method public T inheritedNullability(T i);
854                   }
855                   public final class UnspecifiedUpperBound<T> {
856                     ctor public UnspecifiedUpperBound(T ctorParam);
857                     method public T? explicitNullable(T? e);
858                     method public T inheritedNullability(T i);
859                   }
860                 }
861             """
862         )
863     }
864 
865     @RequiresCapabilities(Capability.KOTLIN)
866     @Test
Nullness in type parameter -- suspend funnull867     fun `Nullness in type parameter -- suspend fun`() {
868         check(
869             sourceFiles =
870                 arrayOf(
871                     java(
872                         """
873                         package test.util.concurrent;
874 
875                         public interface MyFuture<V extends @Nullable Object> {
876                         }
877                     """
878                     ),
879                     kotlin(
880                         """
881                         package test.pkg
882 
883                         import test.util.concurrent.MyFuture
884 
885                         suspend fun <T> MyFuture<T>.await(t: T): T = TODO()
886                     """
887                     )
888                 ),
889             api =
890                 """
891                 package test.pkg {
892                   public final class TestKt {
893                     method public static suspend <T> Object? await(test.util.concurrent.MyFuture<T>, T t, kotlin.coroutines.Continuation<? super T>);
894                   }
895                 }
896                 package test.util.concurrent {
897                   public interface MyFuture<V> {
898                   }
899                 }
900             """
901         )
902     }
903 
904     @RequiresCapabilities(Capability.KOTLIN)
905     @Test
Nullness in type parameter -- property and accessornull906     fun `Nullness in type parameter -- property and accessor`() {
907         check(
908             sourceFiles =
909                 arrayOf(
910                     kotlin(
911                         """
912                         package test.pkg
913 
914                         class CircularArray<E> {
915                             val first: E
916                                 get() = TODO()
917 
918                             var last: E
919                                 get() = TODO()
920                                 set(value) = TODO()
921                         }
922                     """
923                     )
924                 ),
925             api =
926                 """
927                 package test.pkg {
928                   public final class CircularArray<E> {
929                     ctor public CircularArray();
930                     method public E getFirst();
931                     method public E getLast();
932                     method public void setLast(E);
933                     property public final E first;
934                     property public final E last;
935                   }
936                 }
937             """
938         )
939     }
940 
941     @RequiresCapabilities(Capability.KOTLIN)
942     @Test
Propagate Platform types in Kotlinnull943     fun `Propagate Platform types in Kotlin`() {
944         check(
945             format = FileFormat.V3,
946             sourceFiles =
947                 arrayOf(
948                     kotlin(
949                         """
950                     // Nullable Pair in Kotlin
951                     package androidx.util
952 
953                     class NullableKotlinPair<out F, out S>(val first: F?, val second: S?)
954                     """
955                     ),
956                     kotlin(
957                         """
958                     // Non-nullable Pair in Kotlin
959                     package androidx.util
960                     class NonNullableKotlinPair<out F: Any, out S: Any>(val first: F, val second: S)
961                     """
962                     ),
963                     java(
964                         """
965                     // Platform nullability Pair in Java
966                     package androidx.util;
967 
968                     @SuppressWarnings("WeakerAccess")
969                     public class PlatformJavaPair<F, S> {
970                         public final F first;
971                         public final S second;
972 
973                         public PlatformJavaPair(F first, S second) {
974                             this.first = first;
975                             this.second = second;
976                         }
977                     }
978                 """
979                     ),
980                     java(
981                         """
982                     // Platform nullability Pair in Java
983                     package androidx.util;
984                     import androidx.annotation.NonNull;
985                     import androidx.annotation.Nullable;
986 
987                     @SuppressWarnings("WeakerAccess")
988                     public class NullableJavaPair<F, S> {
989                         public final @Nullable F first;
990                         public final @Nullable S second;
991 
992                         public NullableJavaPair(@Nullable F first, @Nullable S second) {
993                             this.first = first;
994                             this.second = second;
995                         }
996                     }
997                     """
998                     ),
999                     java(
1000                         """
1001                     // Platform nullability Pair in Java
1002                     package androidx.util;
1003 
1004                     import androidx.annotation.NonNull;
1005 
1006                     @SuppressWarnings("WeakerAccess")
1007                     public class NonNullableJavaPair<F, S> {
1008                         public final @NonNull F first;
1009                         public final @NonNull S second;
1010 
1011                         public NonNullableJavaPair(@NonNull F first, @NonNull S second) {
1012                             this.first = first;
1013                             this.second = second;
1014                         }
1015                     }
1016                     """
1017                     ),
1018                     kotlin(
1019                         """
1020                     package androidx.util
1021 
1022                     @Suppress("HasPlatformType") // Intentionally propagating platform type with unknown nullability.
1023                     inline operator fun <F, S> PlatformJavaPair<F, S>.component1() = first
1024                     """
1025                     ),
1026                     androidxNonNullSource,
1027                     androidxNullableSource
1028                 ),
1029             api =
1030                 """
1031                 // Signature format: 3.0
1032                 package androidx.util {
1033                   public class NonNullableJavaPair<F, S> {
1034                     ctor public NonNullableJavaPair(F, S);
1035                     field public final F first;
1036                     field public final S second;
1037                   }
1038                   public final class NonNullableKotlinPair<F, S> {
1039                     ctor public NonNullableKotlinPair(F first, S second);
1040                     method public F getFirst();
1041                     method public S getSecond();
1042                     property public final F first;
1043                     property public final S second;
1044                   }
1045                   public class NullableJavaPair<F, S> {
1046                     ctor public NullableJavaPair(F?, S?);
1047                     field public final F? first;
1048                     field public final S? second;
1049                   }
1050                   public final class NullableKotlinPair<F, S> {
1051                     ctor public NullableKotlinPair(F? first, S? second);
1052                     method public F? getFirst();
1053                     method public S? getSecond();
1054                     property public final F? first;
1055                     property public final S? second;
1056                   }
1057                   public class PlatformJavaPair<F, S> {
1058                     ctor public PlatformJavaPair(F!, S!);
1059                     field public final F! first;
1060                     field public final S! second;
1061                   }
1062                   public final class TestKt {
1063                     method public static inline operator <F, S> F! component1(androidx.util.PlatformJavaPair<F,S>);
1064                   }
1065                 }
1066                 """,
1067             extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation")
1068         )
1069     }
1070 
1071     @RequiresCapabilities(Capability.KOTLIN)
1072     @Test
Known nullnessnull1073     fun `Known nullness`() {
1074         // Don't emit platform types for some unannotated elements that we know the
1075         // nullness for: annotation type members, equals-parameters, initialized constants, etc.
1076         check(
1077             format = FileFormat.V3,
1078             sourceFiles =
1079                 arrayOf(
1080                     java(
1081                         """
1082                     // Platform nullability Pair in Java
1083                     package test;
1084 
1085                     import androidx.annotation.NonNull;
1086 
1087                     public class MyClass {
1088                         public static final String MY_CONSTANT1 = "constant"; // Not nullable
1089                         public final String MY_CONSTANT2 = "constant"; // Not nullable
1090                         public String MY_CONSTANT3 = "constant"; // Unknown
1091 
1092                         /** @deprecated */
1093                         @Deprecated
1094                         @Override
1095                         public boolean equals(
1096                             Object parameter  // nullable
1097                         ) {
1098                             return super.equals(parameter);
1099                         }
1100 
1101                         /** @deprecated */
1102                         @Deprecated
1103                         @Override // Not nullable
1104                         public String toString() {
1105                             return super.toString();
1106                         }
1107                     }
1108                     """
1109                     ),
1110                     java(
1111                             """
1112                     package test.pkg;
1113 
1114                     import static java.lang.annotation.ElementType.*;
1115                     import java.lang.annotation.*;
1116                     public @interface MyAnnotation {
1117                         String[] value(); // Not nullable
1118                     }
1119                     """
1120                         )
1121                         .indented(),
1122                     java(
1123                         """
1124                     package test.pkg;
1125                     @SuppressWarnings("ALL")
1126                     public enum Foo {
1127                         A, B;
1128                     }
1129                     """
1130                     ),
1131                     kotlin(
1132                             """
1133                     package test.pkg
1134                     enum class Language {
1135                         KOTLIN,
1136                         JAVA
1137                     }
1138                     """
1139                         )
1140                         .indented(),
1141                     kotlin(
1142                             """
1143                     package test.pkg
1144                     class Issue {
1145                         fun setAndroidSpecific(value: Boolean): Issue { return this }
1146                         companion object {
1147                             @JvmStatic
1148                             fun create(
1149                                 id: String,
1150                                 briefDescription: String,
1151                                 explanation: String
1152                             ): Issue {
1153                                 return Issue()
1154                             }
1155                         }
1156                     }
1157                     """
1158                         )
1159                         .indented(),
1160                     kotlin(
1161                             """
1162                     package test.pkg
1163                     object MySingleton {
1164                     }
1165                     """
1166                         )
1167                         .indented(),
1168                     java(
1169                             """
1170                     package test.pkg;
1171                     public class WrongCallDetector {
1172                         public static final Issue ISSUE =
1173                                 Issue.create(
1174                                                 "WrongCall",
1175                                                 "Using wrong draw/layout method",
1176                                                 "Custom views typically need to call `measure()`)
1177                                         .setAndroidSpecific(true));
1178                     }
1179                     """
1180                         )
1181                         .indented(),
1182                     androidxNonNullSource,
1183                     androidxNullableSource
1184                 ),
1185             api =
1186                 """
1187                 // Signature format: 3.0
1188                 package test {
1189                   public class MyClass {
1190                     ctor public MyClass();
1191                     method @Deprecated public boolean equals(Object?);
1192                     method @Deprecated public String toString();
1193                     field public static final String MY_CONSTANT1 = "constant";
1194                     field public final String MY_CONSTANT2 = "constant";
1195                     field public String! MY_CONSTANT3;
1196                   }
1197                 }
1198                 package test.pkg {
1199                   public enum Foo {
1200                     enum_constant public static final test.pkg.Foo A;
1201                     enum_constant public static final test.pkg.Foo B;
1202                   }
1203                   public final class Issue {
1204                     ctor public Issue();
1205                     method public static test.pkg.Issue create(String id, String briefDescription, String explanation);
1206                     method public test.pkg.Issue setAndroidSpecific(boolean value);
1207                     field public static final test.pkg.Issue.Companion Companion;
1208                   }
1209                   public static final class Issue.Companion {
1210                     method public test.pkg.Issue create(String id, String briefDescription, String explanation);
1211                   }
1212                   public enum Language {
1213                     enum_constant public static final test.pkg.Language JAVA;
1214                     enum_constant public static final test.pkg.Language KOTLIN;
1215                   }
1216                   @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface MyAnnotation {
1217                     method public abstract String[] value();
1218                   }
1219                   public final class MySingleton {
1220                     field public static final test.pkg.MySingleton INSTANCE;
1221                   }
1222                   public class WrongCallDetector {
1223                     ctor public WrongCallDetector();
1224                     field public static final test.pkg.Issue ISSUE;
1225                   }
1226                 }
1227                 """,
1228             extraArguments =
1229                 arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation", ARG_KOTLIN_SOURCE, "1.8")
1230         )
1231     }
1232 
1233     @RequiresCapabilities(Capability.KOTLIN)
1234     @Test
JvmOverloadsnull1235     fun JvmOverloads() {
1236         // Regression test for https://github.com/android/android-ktx/issues/366
1237         check(
1238             format = FileFormat.V3,
1239             sourceFiles =
1240                 arrayOf(
1241                     kotlin(
1242                         """
1243                         package androidx.content
1244 
1245                         import android.annotation.SuppressLint
1246                         import android.content.SharedPreferences
1247 
1248                         @SuppressLint("ApplySharedPref")
1249                         @JvmOverloads
1250                         inline fun SharedPreferences.edit(
1251                             commit: Boolean = false,
1252                             action: SharedPreferences.Editor.() -> Unit
1253                         ) {
1254                             val editor = edit()
1255                             action(editor)
1256                             if (commit) {
1257                                 editor.commit()
1258                             } else {
1259                                 editor.apply()
1260                             }
1261                         }
1262 
1263                         @JvmOverloads
1264                         fun String.blahblahblah(firstArg: String = "hello", secondArg: Int = 42, thirdArg: String = "world") {
1265                         }
1266                     """
1267                     )
1268                 ),
1269             api =
1270                 """
1271                 // Signature format: 3.0
1272                 package androidx.content {
1273                   public final class TestKt {
1274                     method public static void blahblahblah(String);
1275                     method public static void blahblahblah(String, String firstArg = "hello");
1276                     method public static void blahblahblah(String, String firstArg = "hello", int secondArg = 42);
1277                     method public static void blahblahblah(String, String firstArg = "hello", int secondArg = 42, String thirdArg = "world");
1278                     method public static inline void edit(android.content.SharedPreferences, boolean commit = false, kotlin.jvm.functions.Function1<? super android.content.SharedPreferences.Editor,kotlin.Unit> action);
1279                     method public static inline void edit(android.content.SharedPreferences, kotlin.jvm.functions.Function1<? super android.content.SharedPreferences.Editor,kotlin.Unit> action);
1280                   }
1281                 }
1282                 """,
1283             extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation")
1284         )
1285     }
1286 
1287     @RequiresCapabilities(Capability.KOTLIN)
1288     @Test
Test JvmStaticnull1289     fun `Test JvmStatic`() {
1290         check(
1291             sourceFiles =
1292                 arrayOf(
1293                     kotlin(
1294                         """
1295                     package test.pkg
1296 
1297                     class SimpleClass {
1298                         companion object {
1299                             @JvmStatic
1300                             fun jvmStaticMethod() {}
1301                             fun nonJvmStaticMethod() {}
1302                         }
1303                     }
1304                 """
1305                     )
1306                 ),
1307             format = FileFormat.V3,
1308             api =
1309                 """
1310                 // Signature format: 3.0
1311                 package test.pkg {
1312                   public final class SimpleClass {
1313                     ctor public SimpleClass();
1314                     method public static void jvmStaticMethod();
1315                     field public static final test.pkg.SimpleClass.Companion Companion;
1316                   }
1317                   public static final class SimpleClass.Companion {
1318                     method public void jvmStaticMethod();
1319                     method public void nonJvmStaticMethod();
1320                   }
1321                 }
1322             """
1323         )
1324     }
1325 
1326     @RequiresCapabilities(Capability.KOTLIN)
1327     @Test
Test JvmFieldnull1328     fun `Test JvmField`() {
1329         check(
1330             sourceFiles =
1331                 arrayOf(
1332                     kotlin(
1333                         """
1334                     package test.pkg
1335 
1336                     class SimpleClass {
1337                         @JvmField
1338                         var jvmField = -1
1339 
1340                         var nonJvmField = -2
1341                     }
1342                 """
1343                     )
1344                 ),
1345             format = FileFormat.V3,
1346             api =
1347                 """
1348                 // Signature format: 3.0
1349                 package test.pkg {
1350                   public final class SimpleClass {
1351                     ctor public SimpleClass();
1352                     method public int getNonJvmField();
1353                     method public void setNonJvmField(int);
1354                     property public final int nonJvmField;
1355                     field public int jvmField;
1356                   }
1357                 }
1358             """
1359         )
1360     }
1361 
1362     @RequiresCapabilities(Capability.KOTLIN)
1363     @Test
Test JvmNamenull1364     fun `Test JvmName`() {
1365         check(
1366             sourceFiles =
1367                 arrayOf(
1368                     kotlin(
1369                         """
1370                     package test.pkg
1371 
1372                     class SimpleClass {
1373                         @get:JvmName("myPropertyJvmGetter")
1374                         var myProperty = -1
1375 
1376                         var anotherProperty = -1
1377                     }
1378                 """
1379                     )
1380                 ),
1381             format = FileFormat.V3,
1382             api =
1383                 """
1384                 // Signature format: 3.0
1385                 package test.pkg {
1386                   public final class SimpleClass {
1387                     ctor public SimpleClass();
1388                     method public int getAnotherProperty();
1389                     method public int myPropertyJvmGetter();
1390                     method public void setAnotherProperty(int);
1391                     method public void setMyProperty(int);
1392                     property public final int anotherProperty;
1393                     property public final int myProperty;
1394                   }
1395                 }
1396             """
1397         )
1398     }
1399 
1400     @RequiresCapabilities(Capability.KOTLIN)
1401     @Test
Test RequiresOptIn and OptInnull1402     fun `Test RequiresOptIn and OptIn`() {
1403         check(
1404             sourceFiles =
1405                 arrayOf(
1406                     kotlin(
1407                         """
1408                     package test.pkg
1409 
1410                     @RequiresOptIn
1411                     @Retention(AnnotationRetention.BINARY)
1412                     @Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
1413                     annotation class ExperimentalBar
1414 
1415                     @ExperimentalBar
1416                     class FancyBar
1417 
1418                     @OptIn(FancyBar::class) // @OptIn should not be tracked as it is not API
1419                     class SimpleClass {
1420                         fun methodUsingFancyBar() {
1421                             val fancyBar = FancyBar()
1422                         }
1423                     }
1424                 """
1425                     )
1426                 ),
1427             format = FileFormat.V3,
1428             api =
1429                 """
1430                 // Signature format: 3.0
1431                 package test.pkg {
1432                   @SuppressCompatibility @kotlin.RequiresOptIn @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.BINARY) @kotlin.annotation.Target(allowedTargets={kotlin.annotation.AnnotationTarget.CLASS, kotlin.annotation.AnnotationTarget.FUNCTION}) public @interface ExperimentalBar {
1433                   }
1434                   @SuppressCompatibility @test.pkg.ExperimentalBar public final class FancyBar {
1435                     ctor public FancyBar();
1436                   }
1437                   public final class SimpleClass {
1438                     ctor public SimpleClass();
1439                     method public void methodUsingFancyBar();
1440                   }
1441                 }
1442             """,
1443             suppressCompatibilityMetaAnnotations = arrayOf("kotlin.RequiresOptIn")
1444         )
1445     }
1446 
1447     @Test
Extract class with genericsnull1448     fun `Extract class with generics`() {
1449         // Basic interface with generics; makes sure <T extends Object> is written as just <T>
1450         // Also include some more complex generics expressions to make sure they're serialized
1451         // correctly (in particular, using fully qualified names instead of what appears in
1452         // the source code.)
1453         check(
1454             format = FileFormat.V2,
1455             sourceFiles =
1456                 arrayOf(
1457                     java(
1458                         """
1459                     package test.pkg;
1460                     @SuppressWarnings("ALL")
1461                     public interface MyInterface<T extends Object>
1462                             extends MyBaseInterface {
1463                     }
1464                     """
1465                     ),
1466                     java(
1467                         """
1468                     package a.b.c;
1469                     @SuppressWarnings("ALL")
1470                     public interface MyStream<T, S extends MyStream<T, S>> extends test.pkg.AutoCloseable {
1471                     }
1472                     """
1473                     ),
1474                     java(
1475                         """
1476                     package test.pkg;
1477                     @SuppressWarnings("ALL")
1478                     public interface MyInterface2<T extends Number>
1479                             extends MyBaseInterface {
1480                         class TtsSpan<C extends MyInterface<?>> { }
1481                         abstract class Range<T extends Comparable<? super T>> {
1482                             protected String myString;
1483                         }
1484                     }
1485                     """
1486                     ),
1487                     java(
1488                         """
1489                     package test.pkg;
1490                     public interface MyBaseInterface {
1491                         void fun(int a, String b);
1492                     }
1493                     """
1494                     ),
1495                     java(
1496                         """
1497                     package test.pkg;
1498                     public interface MyOtherInterface extends MyBaseInterface, AutoCloseable {
1499                         void fun(int a, String b);
1500                     }
1501                     """
1502                     ),
1503                     java(
1504                         """
1505                     package test.pkg;
1506                     public interface AutoCloseable {
1507                     }
1508                     """
1509                     )
1510                 ),
1511             api =
1512                 """
1513                     package a.b.c {
1514                       public interface MyStream<T, S extends a.b.c.MyStream<T, S>> extends test.pkg.AutoCloseable {
1515                       }
1516                     }
1517                     package test.pkg {
1518                       public interface AutoCloseable {
1519                       }
1520                       public interface MyBaseInterface {
1521                         method public void fun(int, String);
1522                       }
1523                       public interface MyInterface<T> extends test.pkg.MyBaseInterface {
1524                       }
1525                       public interface MyInterface2<T extends java.lang.Number> extends test.pkg.MyBaseInterface {
1526                       }
1527                       public abstract static class MyInterface2.Range<T extends java.lang.Comparable<? super T>> {
1528                         ctor public MyInterface2.Range();
1529                         field protected String myString;
1530                       }
1531                       public static class MyInterface2.TtsSpan<C extends test.pkg.MyInterface<?>> {
1532                         ctor public MyInterface2.TtsSpan();
1533                       }
1534                       public interface MyOtherInterface extends test.pkg.MyBaseInterface test.pkg.AutoCloseable {
1535                       }
1536                     }
1537                 """,
1538             extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword")
1539         )
1540     }
1541 
1542     @Test
Basic class without default constructor, has constructors with argsnull1543     fun `Basic class without default constructor, has constructors with args`() {
1544         // Class without private constructors (shouldn't insert default constructor)
1545         check(
1546             sourceFiles =
1547                 arrayOf(
1548                     java(
1549                         """
1550                     package test.pkg;
1551                     public class Foo {
1552                         public Foo(int i) {
1553 
1554                         }
1555                         public Foo(int i, int j) {
1556                         }
1557                     }
1558                     """
1559                     )
1560                 ),
1561             api =
1562                 """
1563                 package test.pkg {
1564                   public class Foo {
1565                     ctor public Foo(int);
1566                     ctor public Foo(int, int);
1567                   }
1568                 }
1569                 """
1570         )
1571     }
1572 
1573     @Test
Basic class without default constructor, has private constructornull1574     fun `Basic class without default constructor, has private constructor`() {
1575         // Class without private constructors; no default constructor should be inserted
1576         check(
1577             sourceFiles =
1578                 arrayOf(
1579                     java(
1580                         """
1581                     package test.pkg;
1582                     @SuppressWarnings("ALL")
1583                     public class Foo {
1584                         private Foo() {
1585                         }
1586                     }
1587                     """
1588                     )
1589                 ),
1590             api =
1591                 """
1592                 package test.pkg {
1593                   public class Foo {
1594                   }
1595                 }
1596                 """
1597         )
1598     }
1599 
1600     @Test
Interface class extractionnull1601     fun `Interface class extraction`() {
1602         // Interface: makes sure the right modifiers etc are shown (and that "package private"
1603         // methods
1604         // in the interface are taken to be public etc)
1605         check(
1606             format = FileFormat.V2,
1607             sourceFiles =
1608                 arrayOf(
1609                     java(
1610                         """
1611                     package test.pkg;
1612                     @SuppressWarnings("ALL")
1613                     public interface Foo {
1614                         void foo();
1615                     }
1616                     """
1617                     )
1618                 ),
1619             api =
1620                 """
1621                 package test.pkg {
1622                   public interface Foo {
1623                     method public void foo();
1624                   }
1625                 }
1626                 """
1627         )
1628     }
1629 
1630     @Test
Enum class extractionnull1631     fun `Enum class extraction`() {
1632         check(
1633             format = FileFormat.V2,
1634             sourceFiles =
1635                 arrayOf(
1636                     java(
1637                         """
1638                     package test.pkg;
1639                     @SuppressWarnings("ALL")
1640                     public enum Foo {
1641                         A, B;
1642                     }
1643                     """
1644                     )
1645                 ),
1646             api =
1647                 """
1648                 package test.pkg {
1649                   public enum Foo {
1650                     enum_constant public static final test.pkg.Foo A;
1651                     enum_constant public static final test.pkg.Foo B;
1652                   }
1653                 }
1654                 """
1655         )
1656     }
1657 
1658     @Test
Enum class -- javanull1659     fun `Enum class -- java`() {
1660         check(
1661             sourceFiles =
1662                 arrayOf(
1663                     java(
1664                         """
1665                     package test.pkg;
1666                     @SuppressWarnings("ALL")
1667                     public enum Foo {
1668                         A, B;
1669                     }
1670                     """
1671                     )
1672                 ),
1673             api =
1674                 """
1675                 package test.pkg {
1676                   public enum Foo {
1677                     enum_constant public static final test.pkg.Foo A;
1678                     enum_constant public static final test.pkg.Foo B;
1679                   }
1680                 }
1681                 """
1682         )
1683     }
1684 
1685     @RequiresCapabilities(Capability.KOTLIN)
1686     @Test
Enum class -- ktnull1687     fun `Enum class -- kt`() {
1688         check(
1689             sourceFiles =
1690                 arrayOf(
1691                     kotlin(
1692                         """
1693                     package test.pkg
1694                     enum class Foo {
1695                         A, B;
1696                     }
1697                     """
1698                     )
1699                 ),
1700             api =
1701                 """
1702                 package test.pkg {
1703                   public enum Foo {
1704                     enum_constant public static final test.pkg.Foo A;
1705                     enum_constant public static final test.pkg.Foo B;
1706                   }
1707                 }
1708                 """,
1709             extraArguments = arrayOf(ARG_KOTLIN_SOURCE, "1.8")
1710         )
1711     }
1712 
1713     @Test
Annotation class extractionnull1714     fun `Annotation class extraction`() {
1715         // Interface: makes sure the right modifiers etc are shown (and that "package private"
1716         // methods
1717         // in the interface are taken to be public etc)
1718         check(
1719             sourceFiles =
1720                 arrayOf(
1721                     java(
1722                         """
1723                     package test.pkg;
1724                     @SuppressWarnings("ALL")
1725                     public @interface Foo {
1726                         String value();
1727                     }
1728                     """
1729                     ),
1730                     java(
1731                         """
1732                     package android.annotation;
1733                     import static java.lang.annotation.ElementType.*;
1734                     import java.lang.annotation.*;
1735                     @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
1736                     @Retention(RetentionPolicy.CLASS)
1737                     @SuppressWarnings("ALL")
1738                     public @interface SuppressLint {
1739                         String[] value();
1740                     }
1741                 """
1742                     )
1743                 ),
1744             api =
1745                 """
1746                 package android.annotation {
1747                   @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.LOCAL_VARIABLE}) public @interface SuppressLint {
1748                     method public abstract String[] value();
1749                   }
1750                 }
1751                 package test.pkg {
1752                   @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface Foo {
1753                     method public abstract String value();
1754                   }
1755                 }
1756                 """
1757         )
1758     }
1759 
1760     @Test
Skip inherited package private methods from private parentsnull1761     fun `Skip inherited package private methods from private parents`() {
1762         // Include public methods from hidden parents too.
1763         // Real life example: StringBuilder.setLength
1764         check(
1765             expectedIssues =
1766                 """
1767                 src/test/pkg/PublicSuper.java:3: error: isContiguous cannot be hidden and abstract when PublicSuper has a visible constructor, in case a third-party attempts to subclass it. [HiddenAbstractMethod]
1768             """,
1769             expectedFail = DefaultLintErrorMessage,
1770             sourceFiles =
1771                 arrayOf(
1772                     java(
1773                         """
1774                     package test.pkg;
1775                     public class MyStringBuilder<A,B> extends AbstractMyStringBuilder<A,B> {
1776                     }
1777                     """
1778                     ),
1779                     java(
1780                         """
1781                     package test.pkg;
1782                     class AbstractMyStringBuilder<C,D> extends PublicSuper<C,D> {
1783                         public void setLength(int length) {
1784                         }
1785                         @Override boolean isContiguous() {
1786                             return true;
1787                         }
1788                         @Override boolean concrete() {
1789                             return false;
1790                         }
1791                     }
1792                     """
1793                     ),
1794                     java(
1795                         """
1796                     package test.pkg;
1797                     public class PublicSuper<E,F> {
1798                         abstract boolean isContiguous();
1799                         boolean concrete() {
1800                             return false;
1801                         }
1802                     }
1803                     """
1804                     )
1805                 ),
1806             api =
1807                 """
1808                 package test.pkg {
1809                   public class MyStringBuilder<A, B> extends test.pkg.PublicSuper<A!,B!> {
1810                     ctor public MyStringBuilder();
1811                     method public void setLength(int);
1812                   }
1813                   public class PublicSuper<E, F> {
1814                     ctor public PublicSuper();
1815                   }
1816                 }
1817                 """
1818         )
1819     }
1820 
1821     @RequiresCapabilities(Capability.KOTLIN)
1822     @Test
Annotation retentionnull1823     fun `Annotation retention`() {
1824         // For annotations where the java.lang.annotation classes themselves are not
1825         // part of the source tree, ensure that we compute the right retention (runtime, meaning
1826         // it should show up in the stubs file.).
1827         check(
1828             format = FileFormat.V3,
1829             extraArguments = arrayOf(ARG_EXCLUDE_ALL_ANNOTATIONS),
1830             sourceFiles =
1831                 arrayOf(
1832                     java(
1833                         """
1834                     package test.pkg;
1835                     public @interface Foo {
1836                         String value();
1837                     }
1838                     """
1839                     ),
1840                     java(
1841                         """
1842                     package android.annotation;
1843                     import static java.lang.annotation.ElementType.*;
1844                     import java.lang.annotation.*;
1845                     @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
1846                     @Retention(RetentionPolicy.CLASS)
1847                     @SuppressWarnings("ALL")
1848                     public @interface SuppressLint {
1849                         String[] value();
1850                     }
1851                     """
1852                     ),
1853                     kotlin(
1854                         """
1855                     package test.pkg
1856 
1857                     @DslMarker
1858                     annotation class ImplicitRuntimeRetention
1859 
1860                     @Retention(AnnotationRetention.RUNTIME)
1861                     annotation class ExplicitRuntimeRetention {
1862                     }
1863                     """
1864                             .trimIndent()
1865                     )
1866                 ),
1867             api =
1868                 """
1869             // Signature format: 3.0
1870             package android.annotation {
1871               @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.LOCAL_VARIABLE}) public @interface SuppressLint {
1872                 method public abstract String[] value();
1873               }
1874             }
1875             package test.pkg {
1876               @kotlin.annotation.Retention(kotlin.annotation.AnnotationRetention.RUNTIME) public @interface ExplicitRuntimeRetention {
1877               }
1878               @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface Foo {
1879                 method public abstract String value();
1880               }
1881               @kotlin.DslMarker public @interface ImplicitRuntimeRetention {
1882               }
1883             }
1884             """
1885                     .trimIndent(),
1886             stubFiles =
1887                 arrayOf(
1888                     // For annotations where the java.lang.annotation classes themselves are not
1889                     // part of the source tree, ensure that we compute the right retention (runtime,
1890                     // meaning
1891                     // it should show up in the stubs file.).
1892                     java(
1893                         """
1894                     package test.pkg;
1895                     @SuppressWarnings({"unchecked", "deprecation", "all"})
1896                     @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS)
1897                     public @interface Foo {
1898                     public java.lang.String value();
1899                     }
1900                     """
1901                     ),
1902                     java(
1903                         """
1904                     package android.annotation;
1905                     @SuppressWarnings({"unchecked", "deprecation", "all"})
1906                     @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS)
1907                     @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.LOCAL_VARIABLE})
1908                     public @interface SuppressLint {
1909                     public java.lang.String[] value();
1910                     }
1911                     """
1912                     )
1913                 )
1914         )
1915     }
1916 
1917     @Test
Superclass signature extractionnull1918     fun `Superclass signature extraction`() {
1919         // Make sure superclass statement is correct; inherited method from parent that has same
1920         // signature isn't included in the child
1921         check(
1922             sourceFiles =
1923                 arrayOf(
1924                     java(
1925                         """
1926                     package test.pkg;
1927                     @SuppressWarnings("ALL")
1928                     public class Foo extends Super {
1929                         @Override public void base() { }
1930                         public void child() { }
1931                     }
1932                     """
1933                     ),
1934                     java(
1935                         """
1936                     package test.pkg;
1937                     @SuppressWarnings("ALL")
1938                     public class Super {
1939                         public void base() { }
1940                     }
1941                     """
1942                     )
1943                 ),
1944             api =
1945                 """
1946                 package test.pkg {
1947                   public class Foo extends test.pkg.Super {
1948                     ctor public Foo();
1949                     method public void child();
1950                   }
1951                   public class Super {
1952                     ctor public Super();
1953                     method public void base();
1954                   }
1955                 }
1956                 """
1957         )
1958     }
1959 
1960     @Test
Extract fields with types and initial valuesnull1961     fun `Extract fields with types and initial values`() {
1962         check(
1963             format = FileFormat.V2,
1964             sourceFiles =
1965                 arrayOf(
1966                     java(
1967                         """
1968                     package test.pkg;
1969                     @SuppressWarnings("ALL")
1970                     public class Foo {
1971                         private int hidden = 1;
1972                         int hidden2 = 2;
1973                         /** @hide */
1974                         int hidden3 = 3;
1975 
1976                         protected int field00; // No value
1977                         public static final boolean field01 = true;
1978                         public static final int field02 = 42;
1979                         public static final long field03 = 42L;
1980                         public static final short field04 = 5;
1981                         public static final byte field05 = 5;
1982                         public static final char field06 = 'c';
1983                         public static final float field07 = 98.5f;
1984                         public static final double field08 = 98.5;
1985                         public static final String field09 = "String with \"escapes\" and \u00a9...";
1986                         public static final double field10 = Double.NaN;
1987                         public static final double field11 = Double.POSITIVE_INFINITY;
1988 
1989                         public static final String GOOD_IRI_CHAR = "a-zA-Z0-9\u00a0-\ud7ff\uf900-\ufdcf\ufdf0-\uffef";
1990                         public static final char HEX_INPUT = 61184;
1991                     }
1992                     """
1993                     )
1994                 ),
1995             api =
1996                 """
1997                 package test.pkg {
1998                   public class Foo {
1999                     ctor public Foo();
2000                     field public static final String GOOD_IRI_CHAR = "a-zA-Z0-9\u00a0-\ud7ff\uf900-\ufdcf\ufdf0-\uffef";
2001                     field public static final char HEX_INPUT = 61184; // 0xef00 '\uef00'
2002                     field protected int field00;
2003                     field public static final boolean field01 = true;
2004                     field public static final int field02 = 42; // 0x2a
2005                     field public static final long field03 = 42L; // 0x2aL
2006                     field public static final short field04 = 5; // 0x5
2007                     field public static final byte field05 = 5; // 0x5
2008                     field public static final char field06 = 99; // 0x0063 'c'
2009                     field public static final float field07 = 98.5f;
2010                     field public static final double field08 = 98.5;
2011                     field public static final String field09 = "String with \"escapes\" and \u00a9...";
2012                     field public static final double field10 = (0.0/0.0);
2013                     field public static final double field11 = (1.0/0.0);
2014                   }
2015                 }
2016                 """
2017         )
2018     }
2019 
2020     @Test
Check all modifiersnull2021     fun `Check all modifiers`() {
2022         // Include as many modifiers as possible to see which ones are included
2023         // in the signature files, and the expected sorting order.
2024         // Note that the signature files treat "deprecated" as a fake modifier.
2025         // Note also how the "protected" modifier on the interface method gets
2026         // promoted to public.
2027         check(
2028             format = FileFormat.V2,
2029             sourceFiles =
2030                 arrayOf(
2031                     java(
2032                         """
2033                     package test.pkg;
2034 
2035                     @SuppressWarnings("ALL")
2036                     public abstract class Foo {
2037                         @Deprecated private static final long field1 = 5;
2038                         @Deprecated private static volatile long field2 = 5;
2039                         @Deprecated public static strictfp final synchronized void method1() { }
2040                         @Deprecated public static final synchronized native void method2();
2041                         @Deprecated protected static final class Inner1 { }
2042                         @Deprecated protected static abstract  class Inner2 { }
2043                         @Deprecated protected interface Inner3 {
2044                             default void method3() { }
2045                             static void method4(final int arg) { }
2046                         }
2047                     }
2048                     """
2049                     )
2050                 ),
2051             expectedIssues =
2052                 """
2053                 src/test/pkg/Foo.java:7: error: Method test.pkg.Foo.method1(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match [DeprecationMismatch]
2054                 src/test/pkg/Foo.java:8: error: Method test.pkg.Foo.method2(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match [DeprecationMismatch]
2055                 src/test/pkg/Foo.java:9: error: Class test.pkg.Foo.Inner1: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match [DeprecationMismatch]
2056                 src/test/pkg/Foo.java:10: error: Class test.pkg.Foo.Inner2: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match [DeprecationMismatch]
2057                 src/test/pkg/Foo.java:11: error: Class test.pkg.Foo.Inner3: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match [DeprecationMismatch]
2058                 """,
2059             expectedFail = DefaultLintErrorMessage,
2060             api =
2061                 """
2062                     package test.pkg {
2063                       public abstract class Foo {
2064                         ctor public Foo();
2065                         method @Deprecated public static final void method1();
2066                         method @Deprecated public static final void method2();
2067                       }
2068                       @Deprecated protected static final class Foo.Inner1 {
2069                         ctor @Deprecated protected Foo.Inner1();
2070                       }
2071                       @Deprecated protected abstract static class Foo.Inner2 {
2072                         ctor @Deprecated protected Foo.Inner2();
2073                       }
2074                       @Deprecated protected static interface Foo.Inner3 {
2075                         method @Deprecated public default void method3();
2076                         method @Deprecated public static void method4(int);
2077                       }
2078                     }
2079                 """
2080         )
2081     }
2082 
2083     @Test
Warn about findViewByIdnull2084     fun `Warn about findViewById`() {
2085         // Include as many modifiers as possible to see which ones are included
2086         // in the signature files, and the expected sorting order.
2087         // Note that the signature files treat "deprecated" as a fake modifier.
2088         // Note also how the "protected" modifier on the interface method gets
2089         // promoted to public.
2090         check(
2091             format = FileFormat.V2,
2092             sourceFiles =
2093                 arrayOf(
2094                     java(
2095                         """
2096                     package test.pkg;
2097                     import android.annotation.Nullable;
2098 
2099                     @SuppressWarnings("ALL")
2100                     public abstract class Foo {
2101                         @Nullable public String findViewById(int id) { return ""; }
2102                     }
2103                     """
2104                     ),
2105                     nullableSource
2106                 ),
2107             expectedIssues =
2108                 """
2109                 src/test/pkg/Foo.java:6: warning: method test.pkg.Foo.findViewById(int) should not be annotated @Nullable; it should be left unspecified to make it a platform type [ExpectedPlatformType]
2110                 """,
2111             extraArguments = arrayOf(ARG_WARNING, "ExpectedPlatformType"),
2112             api =
2113                 """
2114                 package test.pkg {
2115                   public abstract class Foo {
2116                     ctor public Foo();
2117                     method public String findViewById(int);
2118                   }
2119                 }
2120                 """
2121         )
2122     }
2123 
2124     @Test
Remove findViewById type nullness annotationnull2125     fun `Remove findViewById type nullness annotation`() {
2126         check(
2127             sourceFiles =
2128                 arrayOf(
2129                     java(
2130                         """
2131                     package test.pkg;
2132                     import libcore.util.Nullable;
2133 
2134                     @SuppressWarnings("ALL")
2135                     public abstract class Foo {
2136                         public @Nullable String findViewById(int id) { return ""; }
2137                         public @Nullable String notFindViewById(int id) { return ""; }
2138                     }
2139                     """
2140                     ),
2141                     libcoreNullableSource
2142                 ),
2143             expectedIssues =
2144                 """
2145                 src/test/pkg/Foo.java:6: warning: method test.pkg.Foo.findViewById(int) should not be annotated @Nullable; it should be left unspecified to make it a platform type [ExpectedPlatformType]
2146                 """,
2147             extraArguments = arrayOf(ARG_WARNING, "ExpectedPlatformType"),
2148             skipEmitPackages = listOf("libcore.util"),
2149             format =
2150                 FileFormat.V5.copy(
2151                     kotlinNameTypeOrder = true,
2152                     includeTypeUseAnnotations = true,
2153                     kotlinStyleNulls = false
2154                 ),
2155             api =
2156                 """
2157                 package test.pkg {
2158                   public abstract class Foo {
2159                     ctor public Foo();
2160                     method public findViewById(_: int): String;
2161                     method @Nullable public notFindViewById(_: int): @Nullable String;
2162                   }
2163                 }
2164                 """
2165         )
2166     }
2167 
2168     @Test
Package with only hidden classes should be removed from signature filesnull2169     fun `Package with only hidden classes should be removed from signature files`() {
2170         // Checks that if we have packages that are hidden, or contain only hidden or doconly
2171         // classes, the entire package is omitted from the signature file. Note how the
2172         // test.pkg1.sub
2173         // package is not marked @hide, but doclava now treats subpackages of a hidden package
2174         // as also hidden.
2175         check(
2176             sourceFiles =
2177                 arrayOf(
2178                     java(
2179                         """
2180                     ${"/** @hide hidden package */" /* avoid dangling javadoc warning */}
2181                     package test.pkg1;
2182                     """
2183                     ),
2184                     java(
2185                         """
2186                     package test.pkg1;
2187                     @SuppressWarnings("ALL")
2188                     public class Foo {
2189                         // Hidden by package hide
2190                     }
2191                     """
2192                     ),
2193                     java(
2194                         """
2195                     package test.pkg2;
2196                     /** @hide hidden class in this package */
2197                     @SuppressWarnings("ALL")
2198                     public class Bar {
2199                     }
2200                     """
2201                     ),
2202                     java(
2203                         """
2204                     package test.pkg2;
2205                     /** @doconly hidden class in this package */
2206                     @SuppressWarnings("ALL")
2207                     public class Baz {
2208                     }
2209                     """
2210                     ),
2211                     java(
2212                         """
2213                     package test.pkg1.sub;
2214                     // Hidden by @hide in package above
2215                     @SuppressWarnings("ALL")
2216                     public class Test {
2217                     }
2218                     """
2219                     ),
2220                     java(
2221                         """
2222                     package test.pkg3;
2223                     // The only really visible class
2224                     @SuppressWarnings("ALL")
2225                     public class Boo {
2226                     }
2227                     """
2228                     )
2229                 ),
2230             api =
2231                 """
2232                 package test.pkg3 {
2233                   public class Boo {
2234                     ctor public Boo();
2235                   }
2236                 }
2237                 """
2238         )
2239     }
2240 
2241     @Test
Enums can be abstractnull2242     fun `Enums can be abstract`() {
2243         // As per https://bugs.openjdk.java.net/browse/JDK-6287639
2244         // abstract methods in enums should not be listed as abstract,
2245         // but doclava1 does, so replicate this.
2246         // Also checks that we handle both enum fields and regular fields
2247         // and that they are listed separately.
2248 
2249         check(
2250             format = FileFormat.V2,
2251             sourceFiles =
2252                 arrayOf(
2253                     java(
2254                         """
2255                     package test.pkg;
2256 
2257                     @SuppressWarnings("ALL")
2258                     public enum FooBar {
2259                         ABC {
2260                             @Override
2261                             protected void foo() { }
2262                         }, DEF {
2263                             @Override
2264                             protected void foo() { }
2265                         };
2266 
2267                         protected abstract void foo();
2268                         public static int field1 = 1;
2269                         public int field2 = 2;
2270                     }
2271                     """
2272                     )
2273                 ),
2274             api =
2275                 """
2276                 package test.pkg {
2277                   public enum FooBar {
2278                     method protected abstract void foo();
2279                     enum_constant public static final test.pkg.FooBar ABC;
2280                     enum_constant public static final test.pkg.FooBar DEF;
2281                     field public static int field1;
2282                     field public int field2;
2283                   }
2284                 }
2285             """
2286         )
2287     }
2288 
2289     @Test
Check correct throws list for genericsnull2290     fun `Check correct throws list for generics`() {
2291         check(
2292             format = FileFormat.V2,
2293             sourceFiles =
2294                 arrayOf(
2295                     java(
2296                         """
2297                     package test.pkg;
2298 
2299                     import java.util.function.Supplier;
2300 
2301                     @SuppressWarnings("ALL")
2302                     public final class Test<T> {
2303                         public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
2304                             return null;
2305                         }
2306                     }
2307                     """
2308                     )
2309                 ),
2310             api =
2311                 """
2312                 package test.pkg {
2313                   public final class Test<T> {
2314                     ctor public Test();
2315                     method public <X extends java.lang.Throwable> T orElseThrow(java.util.function.Supplier<? extends X>) throws X;
2316                   }
2317                 }
2318                 """
2319         )
2320     }
2321 
2322     @Test
Check various generics signature subtletiesnull2323     fun `Check various generics signature subtleties`() {
2324         // Some additional declarations where PSI default type handling diffs from doclava1
2325         check(
2326             format = FileFormat.V2,
2327             sourceFiles =
2328                 arrayOf(
2329                     java(
2330                         """
2331                     package test.pkg;
2332 
2333                     @SuppressWarnings("ALL")
2334                     public abstract class Collections {
2335                         public static <T extends java.lang.Object & java.lang.Comparable<? super T>> T max(java.util.Collection<? extends T> collection) {
2336                             return null;
2337                         }
2338                         public abstract <T extends java.util.Collection<java.lang.String>> T addAllTo(T t);
2339                         public final class Range<T extends java.lang.Comparable<? super T>> { }
2340                     }
2341                     """
2342                     ),
2343                     java(
2344                         """
2345                     package test.pkg;
2346 
2347                     import java.util.Set;
2348 
2349                     @SuppressWarnings("ALL")
2350                     public class MoreAsserts {
2351                         public static void assertEquals(String arg0, Set<? extends Object> arg1, Set<? extends Object> arg2) { }
2352                         public static void assertEquals(Set<? extends Object> arg1, Set<? extends Object> arg2) { }
2353                     }
2354 
2355                     """
2356                     )
2357                 ),
2358             api =
2359                 """
2360                 package test.pkg {
2361                   public abstract class Collections {
2362                     ctor public Collections();
2363                     method public abstract <T extends java.util.Collection<java.lang.String>> T addAllTo(T);
2364                     method public static <T extends java.lang.Object & java.lang.Comparable<? super T>> T max(java.util.Collection<? extends T>);
2365                   }
2366                   public final class Collections.Range<T extends java.lang.Comparable<? super T>> {
2367                     ctor public Collections.Range();
2368                   }
2369                   public class MoreAsserts {
2370                     ctor public MoreAsserts();
2371                     method public static void assertEquals(String, java.util.Set<?>, java.util.Set<?>);
2372                     method public static void assertEquals(java.util.Set<?>, java.util.Set<?>);
2373                   }
2374                 }
2375                 """
2376         )
2377     }
2378 
2379     @Test
Check instance methods in enumsnull2380     fun `Check instance methods in enums`() {
2381         // Make sure that when we have instance methods in an enum they're handled
2382         // correctly (there's some special casing around enums to insert extra methods
2383         // that was broken, as exposed by ChronoUnit#toString)
2384         check(
2385             format = FileFormat.V2,
2386             sourceFiles =
2387                 arrayOf(
2388                     java(
2389                         """
2390                     package test.pkg;
2391 
2392                     @SuppressWarnings("ALL")
2393                     public interface TempUnit {
2394                         @Override
2395                         String toString();
2396                     }
2397                      """
2398                     ),
2399                     java(
2400                         """
2401                     package test.pkg;
2402 
2403                     @SuppressWarnings("ALL")
2404                     public enum ChronUnit implements TempUnit {
2405                         C, B, A;
2406 
2407                         public String valueOf(int x) {
2408                             return Integer.toString(x + 5);
2409                         }
2410 
2411                         public String values(String separator) {
2412                             return null;
2413                         }
2414 
2415                         @Override
2416                         public String toString() {
2417                             return name();
2418                         }
2419                     }
2420                 """
2421                     )
2422                 ),
2423             importedPackages = emptyList(),
2424             api =
2425                 """
2426                 package test.pkg {
2427                   public enum ChronUnit implements test.pkg.TempUnit {
2428                     method public String valueOf(int);
2429                     method public String values(String);
2430                     enum_constant public static final test.pkg.ChronUnit A;
2431                     enum_constant public static final test.pkg.ChronUnit B;
2432                     enum_constant public static final test.pkg.ChronUnit C;
2433                   }
2434                   public interface TempUnit {
2435                     method public String toString();
2436                   }
2437                 }
2438                 """
2439         )
2440     }
2441 
2442     @Test
Mixing enums and fieldsnull2443     fun `Mixing enums and fields`() {
2444         // Checks sorting order of enum constant values
2445         val source =
2446             """
2447             package java.nio.file.attribute {
2448               public enum AclEntryPermission {
2449                 enum_constant public static final java.nio.file.attribute.AclEntryPermission APPEND_DATA;
2450                 enum_constant public static final java.nio.file.attribute.AclEntryPermission DELETE;
2451                 enum_constant public static final java.nio.file.attribute.AclEntryPermission DELETE_CHILD;
2452                 enum_constant public static final java.nio.file.attribute.AclEntryPermission EXECUTE;
2453                 enum_constant public static final java.nio.file.attribute.AclEntryPermission READ_ACL;
2454                 enum_constant public static final java.nio.file.attribute.AclEntryPermission READ_ATTRIBUTES;
2455                 enum_constant public static final java.nio.file.attribute.AclEntryPermission READ_DATA;
2456                 enum_constant public static final java.nio.file.attribute.AclEntryPermission READ_NAMED_ATTRS;
2457                 enum_constant public static final java.nio.file.attribute.AclEntryPermission SYNCHRONIZE;
2458                 enum_constant public static final java.nio.file.attribute.AclEntryPermission WRITE_ACL;
2459                 enum_constant public static final java.nio.file.attribute.AclEntryPermission WRITE_ATTRIBUTES;
2460                 enum_constant public static final java.nio.file.attribute.AclEntryPermission WRITE_DATA;
2461                 enum_constant public static final java.nio.file.attribute.AclEntryPermission WRITE_NAMED_ATTRS;
2462                 enum_constant public static final java.nio.file.attribute.AclEntryPermission WRITE_OWNER;
2463                 field public static final java.nio.file.attribute.AclEntryPermission ADD_FILE;
2464                 field public static final java.nio.file.attribute.AclEntryPermission ADD_SUBDIRECTORY;
2465                 field public static final java.nio.file.attribute.AclEntryPermission LIST_DIRECTORY;
2466               }
2467             }
2468                     """
2469         check(format = FileFormat.V2, signatureSource = source, api = source)
2470     }
2471 
2472     @Test
Inheriting from package private classes, package private class should be includednull2473     fun `Inheriting from package private classes, package private class should be included`() {
2474         check(
2475             sourceFiles =
2476                 arrayOf(
2477                     java(
2478                         """
2479                     package test.pkg;
2480                     @SuppressWarnings("ALL")
2481                     public class MyClass extends HiddenParent {
2482                         public void method1() { }
2483                     }
2484                     """
2485                     ),
2486                     java(
2487                         """
2488                     package test.pkg;
2489                     @SuppressWarnings("ALL")
2490                     class HiddenParent {
2491                         public static final String CONSTANT = "MyConstant";
2492                         protected int mContext;
2493                         public void method2() { }
2494                     }
2495                     """
2496                     )
2497                 ),
2498             expectedIssues = "",
2499             api =
2500                 """
2501                     package test.pkg {
2502                       public class MyClass {
2503                         ctor public MyClass();
2504                         method public void method1();
2505                         method public void method2();
2506                         field public static final String CONSTANT = "MyConstant";
2507                       }
2508                     }
2509             """
2510         )
2511     }
2512 
2513     @Test
Inheriting generic method from package private classnull2514     fun `Inheriting generic method from package private class`() {
2515         check(
2516             format = FileFormat.V2,
2517             sourceFiles =
2518                 arrayOf(
2519                     java(
2520                         """
2521                     package test.pkg;
2522                     @SuppressWarnings("ALL")
2523                     public class MyClass extends HiddenParent {
2524                         public void method1() { }
2525                     }
2526                     """
2527                     ),
2528                     java(
2529                         """
2530                     package test.pkg;
2531                     @SuppressWarnings("ALL")
2532                     class HiddenParent {
2533                         public <T> T method2(T t) { }
2534                         public String method3(String s) { }
2535                     }
2536                     """
2537                     )
2538                 ),
2539             expectedIssues = "",
2540             api =
2541                 """
2542                     package test.pkg {
2543                       public class MyClass {
2544                         ctor public MyClass();
2545                         method public void method1();
2546                         method public <T> T method2(T);
2547                         method public String method3(String);
2548                       }
2549                     }
2550             """
2551         )
2552     }
2553 
2554     @Test
Type substitution for generic method referencing parent type parameternull2555     fun `Type substitution for generic method referencing parent type parameter`() {
2556         // Type parameters from parent classes need to be replaced with their bounds in the child.
2557         check(
2558             format = FileFormat.V2,
2559             sourceFiles =
2560                 arrayOf(
2561                     java(
2562                         """
2563                     package test.pkg;
2564                     @SuppressWarnings("ALL")
2565                     public class MyClass extends HiddenParent<String> {
2566                         public void method1() { }
2567                     }
2568                     """
2569                     ),
2570                     java(
2571                         """
2572                     package test.pkg;
2573                     @SuppressWarnings("ALL")
2574                     class HiddenParent<T> {
2575                         public T method2(T t) { }
2576                     }
2577                     """
2578                     )
2579                 ),
2580             expectedIssues = "",
2581             api =
2582                 """
2583                     package test.pkg {
2584                       public class MyClass {
2585                         ctor public MyClass();
2586                         method public void method1();
2587                         method public String method2(String);
2588                       }
2589                     }
2590             """
2591         )
2592     }
2593 
2594     @Test
Check generic type signature insertionnull2595     fun `Check generic type signature insertion`() {
2596         check(
2597             format = FileFormat.V2,
2598             sourceFiles =
2599                 arrayOf(
2600                     java(
2601                         """
2602                     package test.pkg;
2603                     public class MyClass {
2604                         public <T> MyClass(Class<T> klass) { }
2605                         public <U> void method1(Function<U> func) { }
2606                     }
2607                     """
2608                     )
2609                 ),
2610             expectedIssues = "",
2611             api =
2612                 """
2613                     package test.pkg {
2614                       public class MyClass {
2615                         ctor public <T> MyClass(Class<T>);
2616                         method public <U> void method1(Function<U>);
2617                       }
2618                     }
2619             """
2620         )
2621     }
2622 
2623     @Test
When implementing rather than extending package private class, inline members insteadnull2624     fun `When implementing rather than extending package private class, inline members instead`() {
2625         // If you implement a package private interface, we just remove it and inline the members
2626         // into
2627         // the subclass
2628         check(
2629             sourceFiles =
2630                 arrayOf(
2631                     java(
2632                         """
2633                     package test.pkg;
2634                     public class MyClass implements HiddenInterface {
2635                         @Override public void method() { }
2636                         @Override public void other() { }
2637                     }
2638                     """
2639                     ),
2640                     java(
2641                         """
2642                     package test.pkg;
2643                     public interface OtherInterface {
2644                         void other();
2645                     }
2646                     """
2647                     ),
2648                     java(
2649                         """
2650                     package test.pkg;
2651                     interface HiddenInterface extends OtherInterface {
2652                         void method() { }
2653                         String CONSTANT = "MyConstant";
2654                     }
2655                     """
2656                     )
2657                 ),
2658             api =
2659                 """
2660                 package test.pkg {
2661                   public class MyClass implements test.pkg.OtherInterface {
2662                     ctor public MyClass();
2663                     method public void method();
2664                     method public void other();
2665                     field public static final String CONSTANT = "MyConstant";
2666                   }
2667                   public interface OtherInterface {
2668                     method public void other();
2669                   }
2670                 }
2671                 """
2672         )
2673     }
2674 
2675     @Test
Implementing package private classnull2676     fun `Implementing package private class`() {
2677         // Include all the non-hidden public interfaces into the signature
2678 
2679         // BUG: Note that we need to implement the parent
2680         check(
2681             sourceFiles =
2682                 arrayOf(
2683                     java(
2684                         """
2685                     package test.pkg;
2686                     public class MyClass implements HiddenInterface {
2687                         @Override public void method() { }
2688                         @Override public void other() { }
2689                     }
2690                     """
2691                     ),
2692                     java(
2693                         """
2694                     package test.pkg;
2695                     public interface OtherInterface {
2696                         void other();
2697                     }
2698                     """
2699                     ),
2700                     java(
2701                         """
2702                     package test.pkg;
2703                     interface HiddenInterface extends OtherInterface {
2704                         void method() { }
2705                         String CONSTANT = "MyConstant";
2706                     }
2707                     """
2708                     )
2709                 ),
2710             api =
2711                 """
2712                 package test.pkg {
2713                   public class MyClass implements test.pkg.OtherInterface {
2714                     ctor public MyClass();
2715                     method public void method();
2716                     method public void other();
2717                     field public static final String CONSTANT = "MyConstant";
2718                   }
2719                   public interface OtherInterface {
2720                     method public void other();
2721                   }
2722                 }
2723                 """
2724         )
2725     }
2726 
2727     @Test
Default modifiers should be omittednull2728     fun `Default modifiers should be omitted`() {
2729         // If signatures vary only by the "default" modifier in the interface, don't show it on the
2730         // implementing
2731         // class
2732         check(
2733             format = FileFormat.V2,
2734             sourceFiles =
2735                 arrayOf(
2736                     java(
2737                         """
2738                     package test.pkg;
2739 
2740                     public class MyClass implements SuperInterface {
2741                         @Override public void method() {  }
2742                         @Override public void method2() { }
2743                     }
2744                     """
2745                     ),
2746                     java(
2747                         """
2748                     package test.pkg;
2749 
2750                     public interface SuperInterface {
2751                         void method();
2752                         default void method2() {
2753                         }
2754                     }
2755                     """
2756                     )
2757                 ),
2758             api =
2759                 """
2760                 package test.pkg {
2761                   public class MyClass implements test.pkg.SuperInterface {
2762                     ctor public MyClass();
2763                     method public void method();
2764                   }
2765                   public interface SuperInterface {
2766                     method public void method();
2767                     method public default void method2();
2768                   }
2769                 }
2770             """
2771         )
2772     }
2773 
2774     @Test
Override via different throws list should be includednull2775     fun `Override via different throws list should be included`() {
2776         // If a method overrides another but changes the throws list, the overriding
2777         // method must be listed in the subclass. This is observed for example in
2778         // AbstractCursor#finalize, which omits the throws clause from Object's finalize.
2779         check(
2780             sourceFiles =
2781                 arrayOf(
2782                     java(
2783                         """
2784                     package test.pkg;
2785 
2786                     public abstract class AbstractCursor extends Parent {
2787                         @Override protected void finalize2() {  } // note: not throws Throwable!
2788                     }
2789                     """
2790                     ),
2791                     java(
2792                         """
2793                     package test.pkg;
2794 
2795                     @SuppressWarnings("RedundantThrows")
2796                     public class Parent {
2797                         protected void finalize2() throws Throwable {
2798                         }
2799                     }
2800                     """
2801                     )
2802                 ),
2803             api =
2804                 """
2805                 package test.pkg {
2806                   public abstract class AbstractCursor extends test.pkg.Parent {
2807                     ctor public AbstractCursor();
2808                     method protected void finalize2();
2809                   }
2810                   public class Parent {
2811                     ctor public Parent();
2812                     method protected void finalize2() throws java.lang.Throwable;
2813                   }
2814                 }
2815             """
2816         )
2817     }
2818 
2819     @Test
Implementing interface methodnull2820     fun `Implementing interface method`() {
2821         // If you have a public method that implements an interface method,
2822         // they'll vary in the "abstract" modifier, but it shouldn't be listed on the
2823         // class. This is an issue for example for the ZonedDateTime#getLong method
2824         // implementing the TemporalAccessor#getLong method
2825         check(
2826             format = FileFormat.V2,
2827             sourceFiles =
2828                 arrayOf(
2829                     java(
2830                         """
2831                     package test.pkg;
2832                     public interface SomeInterface2 {
2833                         @Override default long getLong() {
2834                             return 42;
2835                         }
2836                     }
2837                     """
2838                     ),
2839                     java(
2840                         """
2841                     package test.pkg;
2842                     public class Foo implements SomeInterface2 {
2843                         @Override
2844                         public long getLong() { return 0L; }
2845                     }
2846                     """
2847                     )
2848                 ),
2849             api =
2850                 """
2851             package test.pkg {
2852               public class Foo implements test.pkg.SomeInterface2 {
2853                 ctor public Foo();
2854               }
2855               public interface SomeInterface2 {
2856                 method public default long getLong();
2857               }
2858             }
2859         """
2860         )
2861     }
2862 
2863     @Test
Implementing interface method 2null2864     fun `Implementing interface method 2`() {
2865         check(
2866             format = FileFormat.V2,
2867             sourceFiles =
2868                 arrayOf(
2869                     java(
2870                         """
2871                     package test.pkg;
2872                     public interface SomeInterface {
2873                         long getLong();
2874                     }
2875                     """
2876                     ),
2877                     java(
2878                         """
2879                     package test.pkg;
2880                     public interface SomeInterface2 {
2881                         @Override default long getLong() {
2882                             return 42;
2883                         }
2884                     }
2885                     """
2886                     ),
2887                     java(
2888                         """
2889                     package test.pkg;
2890                     public class Foo implements SomeInterface, SomeInterface2 {
2891                         @Override
2892                         public long getLong() { return 0L; }
2893                     }
2894                     """
2895                     )
2896                 ),
2897             api =
2898                 """
2899                 package test.pkg {
2900                   public class Foo implements test.pkg.SomeInterface test.pkg.SomeInterface2 {
2901                     ctor public Foo();
2902                   }
2903                   public interface SomeInterface {
2904                     method public long getLong();
2905                   }
2906                   public interface SomeInterface2 {
2907                     method public default long getLong();
2908                   }
2909                 }
2910                 """
2911         )
2912     }
2913 
2914     @Test
Check basic @remove scenariosnull2915     fun `Check basic @remove scenarios`() {
2916         // Test basic @remove handling for methods and fields
2917         check(
2918             sourceFiles =
2919                 arrayOf(
2920                     java(
2921                         """
2922                     package test.pkg;
2923                     @SuppressWarnings("JavaDoc")
2924                     public class Bar {
2925                         /** @removed */
2926                         public Bar() { }
2927                         public int field;
2928                         public void test() { }
2929                         /** @removed */
2930                         public int removedField;
2931                         /** @removed */
2932                         public void removedMethod() { }
2933                         /** @removed and @hide - should not be listed */
2934                         public int hiddenField;
2935 
2936                         /** @removed */
2937                         public class Inner { }
2938 
2939                         public class Inner2 {
2940                             public class Inner3 {
2941                                 /** @removed */
2942                                 public class Inner4 { }
2943                             }
2944                         }
2945 
2946                         public class Inner5 {
2947                             public class Inner6 {
2948                                 public class Inner7 {
2949                                     /** @removed */
2950                                     public int removed;
2951                                 }
2952                             }
2953                         }
2954                     }
2955                     """
2956                     )
2957                 ),
2958             removedApi =
2959                 """
2960                 package test.pkg {
2961                   public class Bar {
2962                     ctor public Bar();
2963                     method public void removedMethod();
2964                     field public int removedField;
2965                   }
2966                   public class Bar.Inner {
2967                     ctor public Bar.Inner();
2968                   }
2969                   public class Bar.Inner2.Inner3.Inner4 {
2970                     ctor public Bar.Inner2.Inner3.Inner4();
2971                   }
2972                   public class Bar.Inner5.Inner6.Inner7 {
2973                     field public int removed;
2974                   }
2975                 }
2976                 """
2977         )
2978     }
2979 
2980     @Test
Check @remove classnull2981     fun `Check @remove class`() {
2982         // Test removing classes
2983         check(
2984             format = FileFormat.V2,
2985             sourceFiles =
2986                 arrayOf(
2987                     java(
2988                         """
2989                     package test.pkg;
2990                     /** @removed */
2991                     @SuppressWarnings("JavaDoc")
2992                     public class Foo {
2993                         public void foo() { }
2994                         public class Inner {
2995                         }
2996                     }
2997                     """
2998                     ),
2999                     java(
3000                         """
3001                     package test.pkg;
3002                     @SuppressWarnings("JavaDoc")
3003                     public class Bar implements Parcelable {
3004                         public int field;
3005                         public void method();
3006 
3007                         /** @removed */
3008                         public int removedField;
3009                         /** @removed */
3010                         public void removedMethod() { }
3011 
3012                         public class Inner1 {
3013                         }
3014                         /** @removed */
3015                         public class Inner2 {
3016                         }
3017                     }
3018                     """
3019                     ),
3020                     java(
3021                         """
3022                     package test.pkg;
3023                     @SuppressWarnings("ALL")
3024                     public interface Parcelable {
3025                         void method();
3026                     }
3027                     """
3028                     )
3029                 ),
3030             /*
3031             I expected this: but doclava1 doesn't do that (and we now match its behavior)
3032             package test.pkg {
3033               public class Bar {
3034                 method public void removedMethod();
3035                 field public int removedField;
3036               }
3037               public class Bar.Inner2 {
3038               }
3039               public class Foo {
3040                 method public void foo();
3041               }
3042             }
3043              */
3044             removedApi =
3045                 """
3046                     package test.pkg {
3047                       public class Bar implements test.pkg.Parcelable {
3048                         method public void removedMethod();
3049                         field public int removedField;
3050                       }
3051                       public class Bar.Inner2 {
3052                         ctor public Bar.Inner2();
3053                       }
3054                       public class Foo {
3055                         ctor public Foo();
3056                         method public void foo();
3057                       }
3058                       public class Foo.Inner {
3059                         ctor public Foo.Inner();
3060                       }
3061                     }
3062                 """
3063         )
3064     }
3065 
3066     @Test
Test include overridden @Deprecated even if annotated with @hidenull3067     fun `Test include overridden @Deprecated even if annotated with @hide`() {
3068         check(
3069             format = FileFormat.V2,
3070             sourceFiles =
3071                 arrayOf(
3072                     java(
3073                         """
3074                     package test.pkg;
3075                     @SuppressWarnings("JavaDoc")
3076                     public class Child extends Parent {
3077                         /**
3078                         * @deprecated
3079                         * @hide
3080                         */
3081                         @Deprecated @Override
3082                         public String toString() {
3083                             return "Child";
3084                         }
3085 
3086                         /**
3087                          * @hide
3088                          */
3089                         public void hiddenApi() {
3090                         }
3091                     }
3092                     """
3093                     ),
3094                     java(
3095                         """
3096                     package test.pkg;
3097                     public class Parent {
3098                         public String toString() {
3099                             return "Parent";
3100                         }
3101                     }
3102                     """
3103                     )
3104                 ),
3105             api =
3106                 """
3107                     package test.pkg {
3108                       public class Child extends test.pkg.Parent {
3109                         ctor public Child();
3110                         method @Deprecated public String toString();
3111                       }
3112                       public class Parent {
3113                         ctor public Parent();
3114                       }
3115                     }
3116                     """,
3117             dexApi =
3118                 """
3119                 Ltest/pkg/Child;
3120                 Ltest/pkg/Child;-><init>()V
3121                 Ltest/pkg/Child;->toString()Ljava/lang/String;
3122                 Ltest/pkg/Parent;
3123                 Ltest/pkg/Parent;-><init>()V
3124                 Ltest/pkg/Parent;->toString()Ljava/lang/String;
3125             """
3126         )
3127     }
3128 
3129     @RequiresCapabilities(Capability.KOTLIN)
3130     @Test
Test invalid class namenull3131     fun `Test invalid class name`() {
3132         // Regression test for b/73018978
3133         check(
3134             format = FileFormat.V2,
3135             sourceFiles =
3136                 arrayOf(
3137                     kotlin(
3138                         "src/test/pkg/Foo.kt",
3139                         """
3140                     @file:JvmName("-Foo")
3141 
3142                     package test.pkg
3143 
3144                     @Suppress("unused")
3145                     inline fun String.printHelloWorld() { println("Hello World") }
3146                     """
3147                     )
3148                 ),
3149             api =
3150                 """
3151                 package test.pkg {
3152                   public final class -Foo {
3153                     method public static inline void printHelloWorld(@NonNull String);
3154                   }
3155                 }
3156                 """
3157         )
3158     }
3159 
3160     @Test
Indirect Field Includes from Interfacesnull3161     fun `Indirect Field Includes from Interfaces`() {
3162         // Real-world example: include ZipConstants into ZipFile and JarFile
3163         check(
3164             sourceFiles =
3165                 arrayOf(
3166                     java(
3167                         """
3168                     package test.pkg1;
3169                     interface MyConstants {
3170                         long CONSTANT1 = 12345;
3171                         long CONSTANT2 = 67890;
3172                         long CONSTANT3 = 42;
3173                     }
3174                     """
3175                     ),
3176                     java(
3177                         """
3178                     package test.pkg1;
3179                     import java.io.Closeable;
3180                     @SuppressWarnings("WeakerAccess")
3181                     public class MyParent implements MyConstants, Closeable {
3182                     }
3183                     """
3184                     ),
3185                     java(
3186                         """
3187                     package test.pkg2;
3188 
3189                     import test.pkg1.MyParent;
3190                     public class MyChild extends MyParent {
3191                     }
3192                     """
3193                     )
3194                 ),
3195             api =
3196                 """
3197                     package test.pkg1 {
3198                       public class MyParent implements java.io.Closeable {
3199                         ctor public MyParent();
3200                         field public static final long CONSTANT1 = 12345L; // 0x3039L
3201                         field public static final long CONSTANT2 = 67890L; // 0x10932L
3202                         field public static final long CONSTANT3 = 42L; // 0x2aL
3203                       }
3204                     }
3205                     package test.pkg2 {
3206                       public class MyChild extends test.pkg1.MyParent {
3207                         ctor public MyChild();
3208                         field public static final long CONSTANT1 = 12345L; // 0x3039L
3209                         field public static final long CONSTANT2 = 67890L; // 0x10932L
3210                         field public static final long CONSTANT3 = 42L; // 0x2aL
3211                       }
3212                     }
3213                 """
3214         )
3215     }
3216 
3217     @Test
Skip interfaces from packages explicitly hidden via argumentsnull3218     fun `Skip interfaces from packages explicitly hidden via arguments`() {
3219         // Real-world example: HttpResponseCache implements OkCacheContainer but hides the only
3220         // inherited method
3221         check(
3222             extraArguments = arrayOf(ARG_HIDE_PACKAGE, "com.squareup.okhttp"),
3223             sourceFiles =
3224                 arrayOf(
3225                     java(
3226                         """
3227                     package android.net.http;
3228                     import com.squareup.okhttp.Cache;
3229                     import com.squareup.okhttp.OkCacheContainer;
3230                     import java.io.Closeable;
3231                     import java.net.ResponseCache;
3232                     @SuppressWarnings("JavaDoc")
3233                     public final class HttpResponseCache implements Closeable, OkCacheContainer {
3234                         /** @hide Needed for OkHttp integration. */
3235                         @Override
3236                         public Cache getCache() {
3237                             return delegate.getCache();
3238                         }
3239                     }
3240                     """
3241                     ),
3242                     java(
3243                         """
3244                     package com.squareup.okhttp;
3245                     public interface OkCacheContainer {
3246                       Cache getCache();
3247                     }
3248                     """
3249                     ),
3250                     java(
3251                         """
3252                     package com.squareup.okhttp;
3253                     public class Cache {
3254                     }
3255                     """
3256                     )
3257                 ),
3258             expectedIssues =
3259                 """
3260                 src/android/net/http/HttpResponseCache.java:7: warning: Public class android.net.http.HttpResponseCache stripped of unavailable superclass com.squareup.okhttp.OkCacheContainer [HiddenSuperclass]
3261             """,
3262             api =
3263                 """
3264                 package android.net.http {
3265                   public final class HttpResponseCache implements java.io.Closeable {
3266                     ctor public HttpResponseCache();
3267                   }
3268                 }
3269                 """
3270         )
3271     }
3272 
3273     @Test
Test whether partial or total orderingnull3274     fun `Test whether partial or total ordering`() {
3275         check(
3276             format = FileFormat.V2,
3277             checkCompilation = true,
3278             sourceFiles =
3279                 arrayOf(
3280                     java(
3281                         """
3282                     package mine;
3283 
3284                     public interface Bar {
3285                     }
3286                     """
3287                     ),
3288                     java(
3289                         """
3290                     package other;
3291 
3292                     public interface Bar {
3293                     }
3294                     """
3295                     ),
3296                     java(
3297                         """
3298                     package test.pkg;
3299                     public interface FooMineFirst extends mine.Bar, other.Bar {
3300                     }
3301                     """
3302                     ),
3303                     java(
3304                         """
3305                     package test.pkg;
3306                     public interface FooOtherFirst extends other.Bar, mine.Bar {
3307                     }
3308                     """
3309                     ),
3310                 ),
3311             api =
3312                 """
3313                 package mine {
3314                   public interface Bar {
3315                   }
3316                 }
3317                 package other {
3318                   public interface Bar {
3319                   }
3320                 }
3321                 package test.pkg {
3322                   public interface FooMineFirst extends mine.Bar other.Bar {
3323                   }
3324                   public interface FooOtherFirst extends other.Bar mine.Bar {
3325                   }
3326                 }
3327                 """,
3328         )
3329     }
3330 
3331     @Test
Test whether partial or total ordering -  sort-whole-extends-list=yesnull3332     fun `Test whether partial or total ordering -  sort-whole-extends-list=yes`() {
3333         check(
3334             format = FileFormat.V2.copy(specifiedSortWholeExtendsList = true),
3335             checkCompilation = true,
3336             sourceFiles =
3337                 arrayOf(
3338                     java(
3339                         """
3340                     package mine;
3341 
3342                     public interface Bar {
3343                     }
3344                     """
3345                     ),
3346                     java(
3347                         """
3348                     package other;
3349 
3350                     public interface Bar {
3351                     }
3352                     """
3353                     ),
3354                     java(
3355                         """
3356                     package test.pkg;
3357                     public interface FooMineFirst extends mine.Bar, other.Bar {
3358                     }
3359                     """
3360                     ),
3361                     java(
3362                         """
3363                     package test.pkg;
3364                     public interface FooOtherFirst extends other.Bar, mine.Bar {
3365                     }
3366                     """
3367                     ),
3368                 ),
3369             api =
3370                 """
3371                 package mine {
3372                   public interface Bar {
3373                   }
3374                 }
3375                 package other {
3376                   public interface Bar {
3377                   }
3378                 }
3379                 package test.pkg {
3380                   public interface FooMineFirst extends mine.Bar other.Bar {
3381                   }
3382                   public interface FooOtherFirst extends mine.Bar other.Bar {
3383                   }
3384                 }
3385                 """,
3386         )
3387     }
3388 
3389     @Test
Extend from multiple interfacesnull3390     fun `Extend from multiple interfaces`() {
3391         // Real-world example: XmlResourceParser
3392         check(
3393             format = FileFormat.V2,
3394             checkCompilation = true,
3395             sourceFiles =
3396                 arrayOf(
3397                     java(
3398                         """
3399                     package android.content.res;
3400                     import android.util.AttributeSet;
3401                     import org.xmlpull.v1.XmlPullParser;
3402                     import my.AutoCloseable;
3403 
3404                     @SuppressWarnings("UnnecessaryInterfaceModifier")
3405                     public interface XmlResourceParser extends XmlPullParser, AttributeSet, AutoCloseable {
3406                         public void close();
3407                     }
3408                     """
3409                     ),
3410                     java(
3411                         """
3412                     package android.util;
3413                     @SuppressWarnings("WeakerAccess")
3414                     public interface AttributeSet {
3415                     }
3416                     """
3417                     ),
3418                     java(
3419                         """
3420                     package my;
3421                     public interface AutoCloseable {
3422                     }
3423                     """
3424                     ),
3425                     java(
3426                         """
3427                     package org.xmlpull.v1;
3428                     @SuppressWarnings("WeakerAccess")
3429                     public interface XmlPullParser {
3430                     }
3431                     """
3432                     )
3433                 ),
3434             api =
3435                 """
3436                 package android.content.res {
3437                   public interface XmlResourceParser extends org.xmlpull.v1.XmlPullParser android.util.AttributeSet my.AutoCloseable {
3438                     method public void close();
3439                   }
3440                 }
3441                 package android.util {
3442                   public interface AttributeSet {
3443                   }
3444                 }
3445                 package my {
3446                   public interface AutoCloseable {
3447                   }
3448                 }
3449                 package org.xmlpull.v1 {
3450                   public interface XmlPullParser {
3451                   }
3452                 }
3453                 """
3454         )
3455     }
3456 
3457     @Test
Extend from multiple interfaces - sort-whole-extends-list=yesnull3458     fun `Extend from multiple interfaces - sort-whole-extends-list=yes`() {
3459         // Real-world example: XmlResourceParser
3460         check(
3461             format = FileFormat.V2.copy(specifiedSortWholeExtendsList = true),
3462             checkCompilation = true,
3463             sourceFiles =
3464                 arrayOf(
3465                     java(
3466                         """
3467                     package android.content.res;
3468                     import android.util.AttributeSet;
3469                     import org.xmlpull.v1.XmlPullParser;
3470                     import my.AutoCloseable;
3471 
3472                     @SuppressWarnings("UnnecessaryInterfaceModifier")
3473                     public interface XmlResourceParser extends XmlPullParser, AttributeSet, AutoCloseable {
3474                         public void close();
3475                     }
3476                     """
3477                     ),
3478                     java(
3479                         """
3480                     package android.util;
3481                     @SuppressWarnings("WeakerAccess")
3482                     public interface AttributeSet {
3483                     }
3484                     """
3485                     ),
3486                     java(
3487                         """
3488                     package my;
3489                     public interface AutoCloseable {
3490                     }
3491                     """
3492                     ),
3493                     java(
3494                         """
3495                     package org.xmlpull.v1;
3496                     @SuppressWarnings("WeakerAccess")
3497                     public interface XmlPullParser {
3498                     }
3499                     """
3500                     )
3501                 ),
3502             api =
3503                 """
3504                 package android.content.res {
3505                   public interface XmlResourceParser extends android.util.AttributeSet my.AutoCloseable org.xmlpull.v1.XmlPullParser {
3506                     method public void close();
3507                   }
3508                 }
3509                 package android.util {
3510                   public interface AttributeSet {
3511                   }
3512                 }
3513                 package my {
3514                   public interface AutoCloseable {
3515                   }
3516                 }
3517                 package org.xmlpull.v1 {
3518                   public interface XmlPullParser {
3519                   }
3520                 }
3521                 """
3522         )
3523     }
3524 
3525     @Test
Test KDoc suppressnull3526     fun `Test KDoc suppress`() {
3527         // Basic class; also checks that default constructor is made explicit
3528         check(
3529             sourceFiles =
3530                 arrayOf(
3531                     java(
3532                         """
3533                     package test.pkg;
3534                     public class Foo {
3535                         private Foo() { }
3536                         /** @suppress */
3537                         public void hidden() {
3538                         }
3539                     }
3540                     """
3541                     ),
3542                     java(
3543                         """
3544                     package test.pkg;
3545                     /**
3546                     * Some comment.
3547                     * @suppress
3548                     */
3549                     public class Hidden {
3550                         private Hidden() { }
3551                         public void hidden() {
3552                         }
3553                         public class Inner {
3554                         }
3555                     }
3556                     """
3557                     )
3558                 ),
3559             api =
3560                 """
3561                     package test.pkg {
3562                       public class Foo {
3563                       }
3564                     }
3565                 """
3566         )
3567     }
3568 
3569     @Test
Check skipping implicit final or deprecated overridenull3570     fun `Check skipping implicit final or deprecated override`() {
3571         // Regression test for 122358225
3572         check(
3573             sourceFiles =
3574                 arrayOf(
3575                     java(
3576                         """
3577                     package test.pkg;
3578 
3579                     public class Parent {
3580                         public void foo1() { }
3581                         public void foo2() { }
3582                         public void foo3() { }
3583                         public void foo4() { }
3584                     }
3585                     """
3586                     ),
3587                     java(
3588                         """
3589                     package test.pkg;
3590 
3591                     public final class Child1 extends Parent {
3592                         private Child1() { }
3593                         public final void foo1() { }
3594                         public void foo2() { }
3595                     }
3596                     """
3597                     ),
3598                     java(
3599                         """
3600                     package test.pkg;
3601 
3602                     /** @deprecated */
3603                     @Deprecated
3604                     public final class Child2 extends Parent {
3605                         private Child2() { }
3606                         /** @deprecated */
3607                         @Deprecated
3608                         public void foo3() { }
3609                         public void foo4() { }
3610                     }
3611                     """
3612                     ),
3613                     java(
3614                         """
3615                     package test.pkg;
3616 
3617                     /** @deprecated */
3618                     @Deprecated
3619                     public final class Child3 extends Parent {
3620                         private Child3() { }
3621                         public final void foo1() { }
3622                         public void foo2() { }
3623                         /** @deprecated */
3624                         @Deprecated
3625                         public void foo3() { }
3626                         /** @deprecated */
3627                         @Deprecated
3628                         public final void foo4() { }
3629                     }
3630                     """
3631                     )
3632                 ),
3633             api =
3634                 """
3635                 package test.pkg {
3636                   public final class Child1 extends test.pkg.Parent {
3637                   }
3638                   @Deprecated public final class Child2 extends test.pkg.Parent {
3639                   }
3640                   @Deprecated public final class Child3 extends test.pkg.Parent {
3641                   }
3642                   public class Parent {
3643                     ctor public Parent();
3644                     method public void foo1();
3645                     method public void foo2();
3646                     method public void foo3();
3647                     method public void foo4();
3648                   }
3649                 }
3650                 """
3651         )
3652     }
3653 
3654     @Test
Ignore synchronized differencesnull3655     fun `Ignore synchronized differences`() {
3656         check(
3657             sourceFiles =
3658                 arrayOf(
3659                     java(
3660                         """
3661                     package test.pkg2;
3662 
3663                     public class Parent {
3664                         public void foo1() { }
3665                         public synchronized void foo2() { }
3666                     }
3667                     """
3668                     ),
3669                     java(
3670                         """
3671                     package test.pkg2;
3672 
3673                     public class Child1 extends Parent {
3674                         private Child1() { }
3675                         public synchronized void foo1() { }
3676                         public void foo2() { }
3677                     }
3678                     """
3679                     )
3680                 ),
3681             api =
3682                 """
3683                 package test.pkg2 {
3684                   public class Child1 extends test.pkg2.Parent {
3685                   }
3686                   public class Parent {
3687                     ctor public Parent();
3688                     method public void foo1();
3689                     method public void foo2();
3690                   }
3691                 }
3692                 """
3693         )
3694     }
3695 
3696     @Test
Skip incorrect inheritnull3697     fun `Skip incorrect inherit`() {
3698         check(
3699             // Simulate test-mock scenario for getIContentProvider
3700             extraArguments = arrayOf("--stub-packages", "android.test.mock"),
3701             expectedIssues =
3702                 "src/android/test/mock/MockContentProvider.java:6: warning: Public class android.test.mock.MockContentProvider stripped of unavailable superclass android.content.ContentProvider [HiddenSuperclass]",
3703             sourceFiles =
3704                 arrayOf(
3705                     java(
3706                         """
3707                     package android.test.mock;
3708 
3709                     import android.content.ContentProvider;
3710                     import android.content.IContentProvider;
3711 
3712                     public abstract class MockContentProvider extends ContentProvider {
3713                         /**
3714                          * Returns IContentProvider which calls back same methods in this class.
3715                          * By overriding this class, we avoid the mechanism hidden behind ContentProvider
3716                          * (IPC, etc.)
3717                          *
3718                          * @hide
3719                          */
3720                         @Override
3721                         public final IContentProvider getIContentProvider() {
3722                             return mIContentProvider;
3723                         }
3724                     }
3725                     """
3726                     ),
3727                     java(
3728                         """
3729                     package android.content;
3730 
3731                     /** @hide */
3732                     public abstract class ContentProvider {
3733                         protected boolean isTemporary() {
3734                             return false;
3735                         }
3736 
3737                         // This is supposed to be @hide, but in turbine-combined/framework.jar included
3738                         // by java_sdk_library like test-mock, it's not; this is what the special
3739                         // flag is used to test
3740                         public IContentProvider getIContentProvider() {
3741                             return null;
3742                         }
3743                     }
3744                     """
3745                     ),
3746                     java(
3747                         """
3748                     package android.content;
3749                     import android.os.IInterface;
3750 
3751                     /**
3752                      * The ipc interface to talk to a content provider.
3753                      * @hide
3754                      */
3755                     public interface IContentProvider extends IInterface {
3756                     }
3757                     """
3758                     ),
3759                     java(
3760                         """
3761                     package android.content;
3762 
3763                     // Not hidden. Here to make sure that we respect stub-packages
3764                     // and exclude it from everything, including signatures.
3765                     public class ClipData {
3766                     }
3767                     """
3768                     )
3769                 ),
3770             api =
3771                 """
3772                 package android.test.mock {
3773                   public abstract class MockContentProvider {
3774                     ctor public MockContentProvider();
3775                   }
3776                 }
3777                 """
3778         )
3779     }
3780 
3781     @RequiresCapabilities(Capability.KOTLIN)
3782     @Test
Test Visible For Testingnull3783     fun `Test Visible For Testing`() {
3784         // Use the otherwise= visibility in signatures
3785         // Regression test for issue 118763806
3786         check(
3787             format = FileFormat.V2,
3788             sourceFiles =
3789                 arrayOf(
3790                     java(
3791                             """
3792                     package test.pkg;
3793                     import androidx.annotation.VisibleForTesting;
3794 
3795                     @SuppressWarnings({"ClassNameDiffersFromFileName", "WeakerAccess"})
3796                     public class ProductionCodeJava {
3797                         private ProductionCodeJava() { }
3798 
3799                         @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
3800                         public void shouldBeProtected() {
3801                         }
3802 
3803                         @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
3804                         protected void shouldBePrivate1() {
3805                         }
3806 
3807                         @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
3808                         public void shouldBePrivate2() {
3809                         }
3810 
3811                         @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
3812                         public void shouldBePackagePrivate() {
3813                         }
3814 
3815                         @VisibleForTesting(otherwise = VisibleForTesting.NONE)
3816                         public void shouldBeHidden() {
3817                         }
3818                     }
3819                     """
3820                         )
3821                         .indented(),
3822                     kotlin(
3823                             """
3824                     package test.pkg
3825                     import androidx.annotation.VisibleForTesting
3826 
3827                     open class ProductionCodeKotlin private constructor() {
3828 
3829                         @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
3830                         fun shouldBeProtected() {
3831                         }
3832 
3833                         @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
3834                         protected fun shouldBePrivate1() {
3835                         }
3836 
3837                         @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
3838                         fun shouldBePrivate2() {
3839                         }
3840 
3841                         @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
3842                         fun shouldBePackagePrivate() {
3843                         }
3844 
3845                         @VisibleForTesting(otherwise = VisibleForTesting.NONE)
3846                         fun shouldBeHidden() {
3847                         }
3848                     }
3849                     """
3850                         )
3851                         .indented(),
3852                     visibleForTestingSource
3853                 ),
3854             api =
3855                 """
3856                 package test.pkg {
3857                   public class ProductionCodeJava {
3858                     method @VisibleForTesting(otherwise=androidx.annotation.VisibleForTesting.PROTECTED) protected void shouldBeProtected();
3859                   }
3860                   public class ProductionCodeKotlin {
3861                     method @VisibleForTesting(otherwise=androidx.annotation.VisibleForTesting.PROTECTED) protected final void shouldBeProtected();
3862                   }
3863                 }
3864                 """,
3865             extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation")
3866         )
3867     }
3868 
3869     @Test
References Deprecatednull3870     fun `References Deprecated`() {
3871         check(
3872             extraArguments =
3873                 arrayOf(ARG_ERROR, "ReferencesDeprecated", ARG_ERROR, "ExtendsDeprecated"),
3874             expectedIssues =
3875                 """
3876             src/test/pkg/MyClass.java:3: error: Parameter references deprecated type test.pkg.DeprecatedClass in test.pkg.MyClass.method1(): this method should also be deprecated [ReferencesDeprecated]
3877             src/test/pkg/MyClass.java:4: error: Return type references deprecated type test.pkg.DeprecatedInterface in test.pkg.MyClass.method2(): this method should also be deprecated [ReferencesDeprecated]
3878             src/test/pkg/MyClass.java:2: error: Extending deprecated super class class test.pkg.DeprecatedClass from test.pkg.MyClass: this class should also be deprecated [ExtendsDeprecated]
3879             src/test/pkg/MyClass.java:2: error: Implementing interface of deprecated type test.pkg.DeprecatedInterface in test.pkg.MyClass: this class should also be deprecated [ExtendsDeprecated]
3880             """,
3881             expectedFail = DefaultLintErrorMessage,
3882             sourceFiles =
3883                 arrayOf(
3884                     java(
3885                         """
3886                     package test.pkg;
3887                     /** @deprecated */
3888                     @Deprecated
3889                     public class DeprecatedClass {
3890                     }
3891                     """
3892                     ),
3893                     java(
3894                         """
3895                     package test.pkg;
3896                     /** @deprecated */
3897                     @Deprecated
3898                     public interface DeprecatedInterface {
3899                     }
3900                     """
3901                     ),
3902                     java(
3903                         """
3904                     package test.pkg;
3905                     public class MyClass extends DeprecatedClass implements DeprecatedInterface {
3906                         public void method1(DeprecatedClass p, int i) { }
3907                         public DeprecatedInterface method2(int i) { return null; }
3908 
3909                         /** @deprecated */
3910                         @Deprecated
3911                         public void method3(DeprecatedClass p, int i) { }
3912                     }
3913                     """
3914                     )
3915                 )
3916         )
3917     }
3918 
3919     @Test
v3 format for qualified references in typesnull3920     fun `v3 format for qualified references in types`() {
3921         check(
3922             format = FileFormat.V3,
3923             sourceFiles =
3924                 arrayOf(
3925                     java(
3926                         """
3927                     package androidx.appcompat.app;
3928                     import android.view.View;
3929                     import android.view.View.OnClickListener;
3930 
3931                     public class ActionBarDrawerToggle {
3932                         private ActionBarDrawerToggle() { }
3933                         public View.OnClickListener getToolbarNavigationClickListener1() {
3934                             return null;
3935                         }
3936                         public OnClickListener getToolbarNavigationClickListener2() {
3937                             return null;
3938                         }
3939                         public android.view.View.OnClickListener getToolbarNavigationClickListener3() {
3940                             return null;
3941                         }
3942                     }
3943                     """
3944                     )
3945                 ),
3946             api =
3947                 """
3948                 // Signature format: 3.0
3949                 package androidx.appcompat.app {
3950                   public class ActionBarDrawerToggle {
3951                     method public android.view.View.OnClickListener! getToolbarNavigationClickListener1();
3952                     method public android.view.View.OnClickListener! getToolbarNavigationClickListener2();
3953                     method public android.view.View.OnClickListener! getToolbarNavigationClickListener3();
3954                   }
3955                 }
3956                 """
3957         )
3958     }
3959 
3960     @RequiresCapabilities(Capability.KOTLIN)
3961     @Test
FooKt class constructors are not publicnull3962     fun `FooKt class constructors are not public`() {
3963         check(
3964             format = FileFormat.V3,
3965             sourceFiles =
3966                 arrayOf(
3967                     kotlin(
3968                         "src/main/java/test/pkg/Foo.kt",
3969                         """
3970                     package test.pkg
3971                     fun myCall() : Boolean = false
3972                     class Bar
3973                     """
3974                     )
3975                 ),
3976             api =
3977                 """
3978                 // Signature format: 3.0
3979                 package test.pkg {
3980                   public final class Bar {
3981                     ctor public Bar();
3982                   }
3983                   public final class FooKt {
3984                     method public static boolean myCall();
3985                   }
3986                 }
3987                 """
3988         )
3989     }
3990 
3991     @Test
Test inherited hidden methods for descendant classes - Package privatenull3992     fun `Test inherited hidden methods for descendant classes - Package private`() {
3993         check(
3994             sourceFiles =
3995                 arrayOf(
3996                     java(
3997                         """
3998                     package test.pkg;
3999                     public class Class4 extends Class3 {
4000                         public void method4() { }
4001                     }
4002                     """
4003                     ),
4004                     java(
4005                         """
4006                     package test.pkg;
4007                     public class Class3 extends Class2 {
4008                         public void method3() { }
4009                     }
4010                     """
4011                     ),
4012                     java(
4013                         """
4014                     package test.pkg;
4015                     class Class2 extends Class1 {
4016                         public void method2() { }
4017                     }
4018                     """
4019                     ),
4020                     java(
4021                         """
4022                     package test.pkg;
4023                     public class Class1 {
4024                         public void method1() { }
4025                     }
4026                     """
4027                     )
4028                 ),
4029             expectedIssues = "",
4030             api =
4031                 """
4032                 package test.pkg {
4033                   public class Class1 {
4034                     ctor public Class1();
4035                     method public void method1();
4036                   }
4037                   public class Class3 extends test.pkg.Class1 {
4038                     ctor public Class3();
4039                     method public void method2();
4040                     method public void method3();
4041                   }
4042                   public class Class4 extends test.pkg.Class3 {
4043                     ctor public Class4();
4044                     method public void method4();
4045                   }
4046                 }
4047                 """
4048         )
4049     }
4050 
4051     @Test
Test inherited hidden methods for descendant classes - Hidden annotationnull4052     fun `Test inherited hidden methods for descendant classes - Hidden annotation`() {
4053         check(
4054             sourceFiles =
4055                 arrayOf(
4056                     java(
4057                         """
4058                     package test.pkg;
4059                     public class Class4 extends Class3 {
4060                         public void method4() { }
4061                     }
4062                     """
4063                     ),
4064                     java(
4065                         """
4066                     package test.pkg;
4067                     public class Class3 extends Class2 {
4068                         public void method3() { }
4069                     }
4070                     """
4071                     ),
4072                     java(
4073                         """
4074                     package test.pkg;
4075                     /** @hide */
4076                     public class Class2 extends Class1 {
4077                         public void method2() { }
4078                     }
4079                     """
4080                     ),
4081                     java(
4082                         """
4083                     package test.pkg;
4084                     public class Class1 {
4085                         public void method1() { }
4086                     }
4087                     """
4088                     )
4089                 ),
4090             expectedIssues =
4091                 "src/test/pkg/Class3.java:2: warning: Public class test.pkg.Class3 stripped of unavailable superclass test.pkg.Class2 [HiddenSuperclass]",
4092             api =
4093                 """
4094                 package test.pkg {
4095                   public class Class1 {
4096                     ctor public Class1();
4097                     method public void method1();
4098                   }
4099                   public class Class3 extends test.pkg.Class1 {
4100                     ctor public Class3();
4101                     method public void method2();
4102                     method public void method3();
4103                   }
4104                   public class Class4 extends test.pkg.Class3 {
4105                     ctor public Class4();
4106                     method public void method4();
4107                   }
4108                 }
4109                 """
4110         )
4111     }
4112 
4113     @Test
Test inherited methods that use genericsnull4114     fun `Test inherited methods that use generics`() {
4115         check(
4116             format = FileFormat.V2,
4117             sourceFiles =
4118                 arrayOf(
4119                     java(
4120                         """
4121                     package test.pkg;
4122                     import androidx.annotation.NonNull;
4123                     public class Class2 extends Class1<String> {
4124                         @Override
4125                         public void method1(String input) { }
4126                         @Override
4127                         public void method2(@NonNull String input) { }
4128                     }
4129                     """
4130                     ),
4131                     java(
4132                         """
4133                     package test.pkg;
4134                     import androidx.annotation.NonNull;
4135                     class Class1<T> {
4136                         public void method1(T input) { }
4137                         public void method2(T input) { }
4138                         public void method3(T input) { }
4139                         @NonNull
4140                         public String method4(T input) { return ""; }
4141                         public T method5(@NonNull String input) { return null; }
4142                     }
4143                     """
4144                     ),
4145                     androidxNonNullSource
4146                 ),
4147             extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation"),
4148             expectedIssues = "",
4149             api =
4150                 """
4151                 package test.pkg {
4152                   public class Class2 {
4153                     ctor public Class2();
4154                     method public void method1(String);
4155                     method public void method2(@NonNull String);
4156                     method public void method3(String);
4157                     method @NonNull public String method4(String);
4158                     method public String method5(@NonNull String);
4159                   }
4160                 }
4161                 """
4162         )
4163     }
4164 
4165     val MERGE_TEST_SOURCE_1 =
4166         """
4167             package test.pkg {
4168               public final class BaseClass {
4169                 method public void method1();
4170               }
4171             }
4172                     """
4173     val MERGE_TEST_SOURCE_2 =
4174         """
4175             package test.pkg {
4176               public final class SubClass extends test.pkg.BaseClass {
4177               }
4178             }
4179                     """
4180     val MERGE_TEST_EXPECTED =
4181         """
4182             package test.pkg {
4183               public final class BaseClass {
4184                 method public void method1();
4185               }
4186               public final class SubClass extends test.pkg.BaseClass {
4187               }
4188             }
4189             """
4190 
4191     @Test
Test can merge API signature files with duplicate classes with constructorsnull4192     fun `Test can merge API signature files with duplicate classes with constructors`() {
4193         val source1 =
4194             """
4195             package Test.pkg {
4196               public class IpcDataCache<Query, Result> {
4197                 ctor public IpcDataCache(int, @NonNull String, @NonNull String, @NonNull String, @NonNull android.os.IpcDataCache.QueryHandler<Query,Result>);
4198                 method public void disableForCurrentProcess();
4199                 method public static void disableForCurrentProcess(@NonNull String);
4200                 method public void invalidateCache();
4201                 method public static void invalidateCache(@NonNull String, @NonNull String);
4202                 method @Nullable public Result query(@NonNull Query);
4203                 field public static final String MODULE_BLUETOOTH = "bluetooth";
4204               }
4205             }
4206                     """
4207         val source2 =
4208             """
4209             package Test.pkg {
4210               public class IpcDataCache<Query, Result> extends android.app.PropertyInvalidatedCache<Query,Result> {
4211                 ctor public IpcDataCache(int, @NonNull String, @NonNull String, @NonNull String, @NonNull android.os.IpcDataCache.QueryHandler<Query,Result>);
4212                 method public static void disableForCurrentProcess(@NonNull String);
4213                 method public static void invalidateCache(@NonNull String, @NonNull String);
4214                 field public static final String MODULE_BLUETOOTH = "bluetooth";
4215                 field public static final String MODULE_SYSTEM = "system_server";
4216                 field public static final String MODULE_TEST = "test";
4217               }
4218             }
4219                     """
4220         val expected =
4221             """
4222             package Test.pkg {
4223               public class IpcDataCache<Query, Result> extends android.app.PropertyInvalidatedCache<Query!,Result!> {
4224                 ctor public IpcDataCache(int, String, String, String, android.os.IpcDataCache.QueryHandler<Query!,Result!>);
4225                 method public void disableForCurrentProcess();
4226                 method public static void disableForCurrentProcess(String);
4227                 method public void invalidateCache();
4228                 method public static void invalidateCache(String, String);
4229                 method public Result? query(Query);
4230                 field public static final String MODULE_BLUETOOTH = "bluetooth";
4231                 field public static final String MODULE_SYSTEM = "system_server";
4232                 field public static final String MODULE_TEST = "test";
4233               }
4234             }
4235                     """
4236         check(
4237             signatureSources = arrayOf(source1, source2),
4238             api = expected,
4239         )
4240     }
4241 
4242     @Test
Test can merge API signature files with generic type classesnull4243     fun `Test can merge API signature files with generic type classes`() {
4244         val source1 =
4245             """
4246             package Test.pkg {
4247               public class LinkedHashMap<K, V> extends java.util.HashMap<K,V> implements java.util.Map<K,V> {
4248                 ctor public LinkedHashMap(int, float);
4249                 ctor public LinkedHashMap(int);
4250                 ctor public LinkedHashMap();
4251                 ctor public LinkedHashMap(java.util.Map<? extends K,? extends V>);
4252                 ctor public LinkedHashMap(int, float, boolean);
4253                 method protected boolean removeEldestEntry(java.util.Map.Entry<K,V>);
4254               }
4255             }
4256             """
4257         val source2 =
4258             """
4259             package Test.pkg {
4260               public class LinkedHashMap<K, V> extends java.util.HashMap<K,V> implements java.util.Map<K,V> {
4261                 method public java.util.Map.Entry<K,V> eldest();
4262               }
4263             }
4264             """
4265         val expected =
4266             """
4267             package Test.pkg {
4268               public class LinkedHashMap<K, V> extends java.util.HashMap<K,V> implements java.util.Map<K,V> {
4269                 ctor public LinkedHashMap(int, float);
4270                 ctor public LinkedHashMap(int);
4271                 ctor public LinkedHashMap();
4272                 ctor public LinkedHashMap(java.util.Map<? extends K,? extends V>);
4273                 ctor public LinkedHashMap(int, float, boolean);
4274                 method public java.util.Map.Entry<K,V> eldest();
4275                 method protected boolean removeEldestEntry(java.util.Map.Entry<K,V>);
4276               }
4277             }
4278             """
4279         check(
4280             signatureSources = arrayOf(source1, source2),
4281             api = expected,
4282             format =
4283                 FileFormat.V2.copy(
4284                     specifiedOverloadedMethodOrder = OverloadedMethodOrder.SOURCE,
4285                 ),
4286         )
4287     }
4288 
4289     @RequiresCapabilities(Capability.KOTLIN)
4290     @Test
Test tracking of @Composable annotation from classpathnull4291     fun `Test tracking of @Composable annotation from classpath`() {
4292         check(
4293             format = FileFormat.V3,
4294             classpath =
4295                 arrayOf(
4296                     /* The following source file, compiled, then ran
4297                     assertEquals("", toBase64gzip(File("path/to/test.jar")))
4298 
4299                         package test.pkg
4300                         @MustBeDocumented
4301                         @Retention(AnnotationRetention.BINARY)
4302                         @Target(
4303                             AnnotationTarget.CLASS,
4304                             AnnotationTarget.FUNCTION,
4305                             AnnotationTarget.TYPE,
4306                             AnnotationTarget.TYPE_PARAMETER,
4307                             AnnotationTarget.PROPERTY
4308                         )
4309                         annotation class Composable
4310                      */
4311                     base64gzip(
4312                         "test.jar",
4313                         "" +
4314                             "H4sIAAAAAAAAAAvwZmbhYmDg4GBw7DIMYwACJgYI4ARiX9cQR11PPzd9ZoYA" +
4315                             "uEKDDsOwTfVM76SBCiSBWARZoa+jn6eba3CInq/bZ98zp328dfUu8nrrap07" +
4316                             "c35zkMEV4wdPHz1lQjJsQieqraxAXJJaXIJiIzangRUVZKdjKFxiZ7vqLyMD" +
4317                             "wwJmiPPgCp3zcwvyixOTclL1knMSi4tbg07nXQ4QsL1eaSFxa5lu65alXxw9" +
4318                             "Kz2WhLyJsMzUUnqaaKkXNJV1l+86JfM+2avXG99tSj4b/4FXJ+CKqnzrjNld" +
4319                             "Fh7TNiwtPm6c/u6M5Pn19+3rmCrar/O8DmrZZCL1xXtqggWXU91LTtkexfqj" +
4320                             "x/c8KdwfnxUb17nuysSkG71773xnPrlU+odqcd6rEwYy19gbv8TUT7zU4RQp" +
4321                             "ttzRXIorvuteddtcllm6Kq0nF1WkndnrYSCj+uFRV7fkzaK1mbfEeaI5Nfn2" +
4322                             "v+P2XJP6rvJg+sXdxS0n/x5jfVY50+tuznbJovTnZ7uCs00lL51rDV0qffXj" +
4323                             "SaPczYGlq8wCdXanhua2R91cr973Zr7nG9VisaWi/503Mp1/e+/Mslkec1Zb" +
4324                             "ePSF2y68VZjn5sQ7qaQmY+6kCTM3fTbrjPlrvbRtwp7jqurzzGSWZ0yewTS3" +
4325                             "kffE16Oh8cdTvt6btOXlEYMtTWkZP3OTrU7erbvKdflkZ9mZU5dPvv2+ZlmF" +
4326                             "Oo/01xbXJVwL5JSCNGwvJkd0JeezTTqYwX6xNHzOTrm3J5et7XD+eJE3VulI" +
4327                             "vYFOkOCSl6t0rix++JQn/oHo3PsLLnM/0ajzP3Cg1kaheGVzzwGjMJEnomu0" +
4328                             "IoI39LVP2VA4/QOHdsWaM3yXmFhdtROCD85q0s1RblaXXZJ1Y+VDTcUy0TdX" +
4329                             "N/Q380V0pFssqeh4rtil2PcPLc2wWSkGCAPTigQQyyMn59K8ksySnNQUvez8" +
4330                             "kpzMvPjc/JTSnNTkhISENCBmSSrTOLvgyIKjDEDzGJlEmHEnVwgQYHjryIBs" +
4331                             "PrI2bPkKBpY0auLIZcgmYMtMMItfOJbBMgOxbn3hOBs5/6BrQ89oMLCg8Qi+" +
4332                             "bIduDHrYI4z5wUQwJgK8WdlAitmAsBzoFg9mEA8ANX1OW9UEAAA="
4333                     )
4334                 ),
4335             sourceFiles =
4336                 arrayOf(
4337                     kotlin(
4338                         """
4339                     package test.pkg
4340                     class RadioGroupScope() {
4341                         @Composable
4342                         fun RadioGroupItem(
4343                             selected: Boolean,
4344                             onSelect: () -> Unit,
4345                             content: @Composable () -> Unit
4346                         ) { }
4347                     }
4348                 """
4349                     )
4350                 ),
4351             expectedIssues = "",
4352             api =
4353                 """
4354                 // Signature format: 3.0
4355                 package test.pkg {
4356                   public final class RadioGroupScope {
4357                     ctor public RadioGroupScope();
4358                     method @test.pkg.Composable public void RadioGroupItem(boolean selected, kotlin.jvm.functions.Function0<kotlin.Unit> onSelect, kotlin.jvm.functions.Function0<kotlin.Unit> content);
4359                   }
4360                 }
4361             """
4362         )
4363     }
4364 
4365     @RequiresCapabilities(Capability.KOTLIN)
4366     @Test
Test for experimental annotations from classpathnull4367     fun `Test for experimental annotations from classpath`() {
4368         check(
4369             format = FileFormat.V3,
4370             classpath =
4371                 arrayOf(
4372                     /* The following source file, compiled, then ran
4373                     assertEquals("", toBase64gzip(File("path/to/test.jar")))
4374 
4375                         package test.pkg
4376                         @RequiresOptIn
4377                         annotation class ExternalExperimentalAnnotation
4378                      */
4379                     base64gzip(
4380                         "test.jar",
4381                         "" +
4382                             "H4sIAAAAAAAAAAvwZmbhYmDg4GCY0GkYxgAETAwQwAnEvq4hjrqefm76zAwB" +
4383                             "cIUGHYZhm+qZ3kkDFUgCsQiyQl9HP0831+AQPV+3z75nTvt46+pd5PXW1Tp3" +
4384                             "5vzmIIMrxg+ePnrKhGQYuq2sQFySWlyCYiM2p4EVFWSnYyjcr3nzUgYjA0Mo" +
4385                             "ULUuskLXipLUorzEHNeKgtSizNzUvJLEHMe8vPySxJLM/Dy95JzE4uLegN1+" +
4386                             "TI4ituWCYtfF9zmaZC3eWHj1RqSEr8FNliMPFm+USkxya4tMYW+Snbv/kXmE" +
4387                             "RNJLd8n3alpqUqVdxuXvLJ/bPXv69SPnAb1pHK/D3K7lX1v/1+n6qWmCuy7k" +
4388                             "npqW5ZHcamegtuXQqgs7FJyeuZW0rG/d+e10uPmmrFgVjtPNa35c+R2/1vNQ" +
4389                             "zEa5qLU98RO3516dFLgzk3mze4Tmv4z1HqeFC45MSnF/sU1lzV9FW86tq+5t" +
4390                             "PLh2jvx81qVMiZ8W53pGBQqHGbw2seKMm59UwBnyPCT86HrdvqzbNsH7n1f6" +
4391                             "Xfs4x+fe6++Xzn/323b/duG2FxvuV9d5WG7Ma98Q+Of5+8JwgUu5cpezIpXX" +
4392                             "/Ft3f010U7nUtujQyiUm7+etPvKsbU/AxF2XihR6OX6W6xnMzX8j1d+lmDfP" +
4393                             "qUYoIqFkgvO897V9l87weldIHNSYJLHbRelARQOnW0rSDB6D1pfeAS2SZ4zk" +
4394                             "E/UO1bToiO306OLecUAaNcrYrBQDhIFRJQHE8sipqTSvJLMkJzVFLzu/JCcz" +
4395                             "Lz43P6U0JzU5ISEhDYhZkso0zi44suAoAzAJMDKJMONOLRAgwPDWkQHZfGRt" +
4396                             "2JI1DCxp1MSRyPFZzIpk8QvHMlhaJNatLxxnIydfdG3o6RwGFjQeITXVoxuN" +
4397                             "Hh8Io8uZCMZOgDcrG0gxGxB2A913HOw3ALXssnFoBAAA"
4398                     )
4399                 ),
4400             sourceFiles =
4401                 arrayOf(
4402                     kotlin(
4403                         """
4404                     package test.pkg
4405 
4406                     @ExternalExperimentalAnnotation
4407                     class ClassUsingExternalExperimentalApi
4408 
4409                     @InLibraryExperimentalAnnotation
4410                     class ClassUsingInLibraryExperimentalApi
4411                 """
4412                     ),
4413                     kotlin(
4414                         """
4415                         package test.pkg
4416                         @RequiresOptIn
4417                         annotation class InLibraryExperimentalAnnotation
4418                     """
4419                     )
4420                 ),
4421             expectedIssues = "",
4422             api =
4423                 """
4424                 // Signature format: 3.0
4425                 package test.pkg {
4426                   @SuppressCompatibility @test.pkg.ExternalExperimentalAnnotation public final class ClassUsingExternalExperimentalApi {
4427                     ctor public ClassUsingExternalExperimentalApi();
4428                   }
4429                   @SuppressCompatibility @test.pkg.InLibraryExperimentalAnnotation public final class ClassUsingInLibraryExperimentalApi {
4430                     ctor public ClassUsingInLibraryExperimentalApi();
4431                   }
4432                   @SuppressCompatibility @kotlin.RequiresOptIn public @interface InLibraryExperimentalAnnotation {
4433                   }
4434                 }
4435                 """,
4436             extraArguments =
4437                 arrayOf(ARG_SUPPRESS_COMPATIBILITY_META_ANNOTATION, "kotlin.RequiresOptIn")
4438         )
4439     }
4440 
4441     @RequiresCapabilities(Capability.KOTLIN)
4442     @Test
Inline suppress compatibility metadata for experimental annotations from classpathnull4443     fun `Inline suppress compatibility metadata for experimental annotations from classpath`() {
4444         check(
4445             format = FileFormat.V3,
4446             classpath =
4447                 arrayOf(
4448                     /* The following source file, compiled, then ran
4449                     assertEquals("", toBase64gzip(File("path/to/test.jar")))
4450 
4451                         package test.pkg
4452                         @RequiresOptIn
4453                         annotation class ExternalExperimentalAnnotation
4454                      */
4455                     base64gzip(
4456                         "test.jar",
4457                         "" +
4458                             "H4sIAAAAAAAAAAvwZmbhYmDg4GCY0GkYxgAETAwQwAnEvq4hjrqefm76zAwB" +
4459                             "cIUGHYZhm+qZ3kkDFUgCsQiyQl9HP0831+AQPV+3z75nTvt46+pd5PXW1Tp3" +
4460                             "5vzmIIMrxg+ePnrKhGQYuq2sQFySWlyCYiM2p4EVFWSnYyjcr3nzUgYjA0Mo" +
4461                             "ULUuskLXipLUorzEHNeKgtSizNzUvJLEHMe8vPySxJLM/Dy95JzE4uLegN1+" +
4462                             "TI4ituWCYtfF9zmaZC3eWHj1RqSEr8FNliMPFm+USkxya4tMYW+Snbv/kXmE" +
4463                             "RNJLd8n3alpqUqVdxuXvLJ/bPXv69SPnAb1pHK/D3K7lX1v/1+n6qWmCuy7k" +
4464                             "npqW5ZHcamegtuXQqgs7FJyeuZW0rG/d+e10uPmmrFgVjtPNa35c+R2/1vNQ" +
4465                             "zEa5qLU98RO3516dFLgzk3mze4Tmv4z1HqeFC45MSnF/sU1lzV9FW86tq+5t" +
4466                             "PLh2jvx81qVMiZ8W53pGBQqHGbw2seKMm59UwBnyPCT86HrdvqzbNsH7n1f6" +
4467                             "Xfs4x+fe6++Xzn/323b/duG2FxvuV9d5WG7Ma98Q+Of5+8JwgUu5cpezIpXX" +
4468                             "/Ft3f010U7nUtujQyiUm7+etPvKsbU/AxF2XihR6OX6W6xnMzX8j1d+lmDfP" +
4469                             "qUYoIqFkgvO897V9l87weldIHNSYJLHbRelARQOnW0rSDB6D1pfeAS2SZ4zk" +
4470                             "E/UO1bToiO306OLecUAaNcrYrBQDhIFRJQHE8sipqTSvJLMkJzVFLzu/JCcz" +
4471                             "Lz43P6U0JzU5ISEhDYhZkso0zi44suAoAzAJMDKJMONOLRAgwPDWkQHZfGRt" +
4472                             "2JI1DCxp1MSRyPFZzIpk8QvHMlhaJNatLxxnIydfdG3o6RwGFjQeITXVoxuN" +
4473                             "Hh8Io8uZCMZOgDcrG0gxGxB2A913HOw3ALXssnFoBAAA"
4474                     )
4475                 ),
4476             sourceFiles =
4477                 arrayOf(
4478                     kotlin(
4479                         """
4480                     package test.pkg
4481 
4482                     @ExternalExperimentalAnnotation
4483                     class ClassUsingExternalExperimentalApi
4484 
4485                     @InLibraryExperimentalAnnotation
4486                     class ClassUsingInLibraryExperimentalApi
4487                 """
4488                     ),
4489                     kotlin(
4490                         """
4491                         package test.pkg
4492                         @RequiresOptIn
4493                         annotation class InLibraryExperimentalAnnotation
4494                     """
4495                     )
4496                 ),
4497             expectedIssues = "",
4498             api =
4499                 """
4500                 // Signature format: 3.0
4501                 package test.pkg {
4502                   @SuppressCompatibility @test.pkg.ExternalExperimentalAnnotation public final class ClassUsingExternalExperimentalApi {
4503                     ctor public ClassUsingExternalExperimentalApi();
4504                   }
4505                   @SuppressCompatibility @test.pkg.InLibraryExperimentalAnnotation public final class ClassUsingInLibraryExperimentalApi {
4506                     ctor public ClassUsingInLibraryExperimentalApi();
4507                   }
4508                   @SuppressCompatibility @kotlin.RequiresOptIn public @interface InLibraryExperimentalAnnotation {
4509                   }
4510                 }
4511             """,
4512             suppressCompatibilityMetaAnnotations = arrayOf("kotlin.RequiresOptIn")
4513         )
4514     }
4515 
4516     @RequiresCapabilities(Capability.KOTLIN)
4517     @Test
@IntRange value in kotlinnull4518     fun `@IntRange value in kotlin`() {
4519         check(
4520             format = FileFormat.V3,
4521             sourceFiles =
4522                 arrayOf(
4523                     kotlin(
4524                         """
4525                     package test.pkg
4526 
4527                     import androidx.annotation.IntRange
4528 
4529                     class KotlinClass(@IntRange(from = 1) val param: Int) {
4530                         constructor(@IntRange(from = 2) val differentParam: Int)
4531                         fun myMethod(@IntRange(from = 3) val methodParam: Int) {}
4532                     }
4533                 """
4534                     ),
4535                     androidxIntRangeSource
4536                 ),
4537             extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation"),
4538             api =
4539                 """
4540                 // Signature format: 3.0
4541                 package test.pkg {
4542                   public final class KotlinClass {
4543                     ctor public KotlinClass(@IntRange(from=1L) int param);
4544                     ctor public KotlinClass(@IntRange(from=2L) int differentParam);
4545                     method public int getParam();
4546                     method public void myMethod(@IntRange(from=3L) int methodParam);
4547                     property public final int param;
4548                   }
4549                 }
4550             """
4551         )
4552     }
4553 
4554     @Test
Annotation value visibilitynull4555     fun `Annotation value visibility`() {
4556         check(
4557             format = FileFormat.V2,
4558             sourceFiles =
4559                 arrayOf(
4560                     java(
4561                         """
4562                     package test.pkg;
4563 
4564                     import androidx.annotation.IntRange;
4565 
4566                     public final class ApiClass {
4567                         private int hiddenConstant = 1;
4568                         public ApiClass(@IntRange(from=1) int x) {}
4569                         public void method(@IntRange(from = hiddenConstant) int x) {}
4570                     }
4571                 """
4572                     ),
4573                     androidxIntRangeSource
4574                 ),
4575             extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation"),
4576             api =
4577                 """
4578                 // Signature format: 2.0
4579                 package test.pkg {
4580                   public final class ApiClass {
4581                     ctor public ApiClass(@IntRange(from=1) int);
4582                     method public void method(@IntRange(from=0x1) int);
4583                   }
4584                 }
4585             """
4586         )
4587     }
4588 
4589     @RequiresCapabilities(Capability.KOTLIN)
4590     @Test
Kotlin properties with overriding getnull4591     fun `Kotlin properties with overriding get`() {
4592         check(
4593             format = FileFormat.V3,
4594             sourceFiles =
4595                 arrayOf(
4596                     kotlin(
4597                         """
4598                     package test.pkg
4599 
4600                     import androidx.annotation.IntRange
4601 
4602                     class KotlinClass() {
4603                         val propertyWithGetter: Boolean get() = true
4604                         val propertyWithNoGetter: Boolean = true
4605                     }
4606                 """
4607                     ),
4608                     androidxIntRangeSource
4609                 ),
4610             extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation"),
4611             api =
4612                 """
4613                 // Signature format: 3.0
4614                 package test.pkg {
4615                   public final class KotlinClass {
4616                     ctor public KotlinClass();
4617                     method public boolean getPropertyWithGetter();
4618                     method public boolean getPropertyWithNoGetter();
4619                     property public final boolean propertyWithGetter;
4620                     property public final boolean propertyWithNoGetter;
4621                   }
4622                 }
4623             """
4624         )
4625     }
4626 
4627     @RequiresCapabilities(Capability.KOTLIN)
4628     @Test
Constructor property trackingnull4629     fun `Constructor property tracking`() {
4630         check(
4631             format = FileFormat.V3,
4632             sourceFiles =
4633                 arrayOf(
4634                     kotlin(
4635                         """
4636                     package test.pkg
4637                     sealed class MyClass(
4638                         val firstConstructorProperty: Int,
4639                         val secondConstructorProperty: Boolean
4640                     ) {
4641                         val nonConstructorProperty: String = "PROP"
4642                     }
4643                     """
4644                     ),
4645                     kotlin(
4646                         """
4647                     package test.pkg
4648                     data class MyDataClass(
4649                         val constructorProperty: String,
4650                         internal val internalConstructorProperty: String
4651                     )
4652                 """
4653                     )
4654                 ),
4655             api =
4656                 """
4657                 // Signature format: 3.0
4658                 package test.pkg {
4659                   public abstract sealed class MyClass {
4660                     method public final int getFirstConstructorProperty();
4661                     method public final String getNonConstructorProperty();
4662                     method public final boolean getSecondConstructorProperty();
4663                     property public final int firstConstructorProperty;
4664                     property public final String nonConstructorProperty;
4665                     property public final boolean secondConstructorProperty;
4666                   }
4667                   public final class MyDataClass {
4668                     ctor public MyDataClass(String constructorProperty, String internalConstructorProperty);
4669                     method public String component1();
4670                     method public test.pkg.MyDataClass copy(String constructorProperty, String internalConstructorProperty);
4671                     method public String getConstructorProperty();
4672                     property public final String constructorProperty;
4673                   }
4674                 }
4675             """
4676         )
4677     }
4678 
4679     @Test
Concise default Values Names in Javanull4680     fun `Concise default Values Names in Java`() {
4681         // Java code which explicitly specifies parameter names
4682         check(
4683             format = FileFormat.V4,
4684             sourceFiles =
4685                 arrayOf(
4686                     java(
4687                         """
4688                     package test.pkg;
4689                     import androidx.annotation.DefaultValue;
4690 
4691                     public class Foo {
4692                         public void foo(
4693                             @DefaultValue("null") String prefix,
4694                             @DefaultValue("\"Hello World\"") String greeting,
4695                             @DefaultValue("42") int meaning) {
4696                         }
4697                     }
4698                     """
4699                     ),
4700                     supportDefaultValue
4701                 ),
4702             api =
4703                 """
4704                 // Signature format: 4.0
4705                 package test.pkg {
4706                   public class Foo {
4707                     ctor public Foo();
4708                     method public void foo(optional String!, optional String!, optional int);
4709                   }
4710                 }
4711                  """,
4712             extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation")
4713         )
4714     }
4715 
4716     @RequiresCapabilities(Capability.KOTLIN)
4717     @Test
Concise default Values and Names in Kotlinnull4718     fun `Concise default Values and Names in Kotlin`() {
4719         // Kotlin code which explicitly specifies parameter names
4720         check(
4721             format = FileFormat.V4,
4722             sourceFiles =
4723                 arrayOf(
4724                     kotlin(
4725                         """
4726                     package test.pkg
4727                     import some.other.pkg.Constants.Misc.SIZE
4728                     import android.graphics.Bitmap
4729                     import android.view.View
4730 
4731                     class Foo(a: String = "1", b: String = "2") {
4732                         fun method1(myInt: Int = 42,
4733                             myInt2: Int? = null,
4734                             myByte: Int = 2 * 21,
4735                             str: String = "hello " + "world",
4736                             vararg args: String) { }
4737 
4738                         fun method2(myInt: Int, myInt2: Int = (2*myInt) * SIZE) { }
4739 
4740                         fun method3(str: String, myInt: Int, myInt2: Int = double(myInt) + str.length) { }
4741 
4742                         fun emptyLambda(sizeOf: () -> Unit = {  }) {}
4743 
4744                         fun View.drawToBitmap(config: Bitmap.Config = Bitmap.Config.ARGB_8888): Bitmap? = null
4745 
4746                         companion object {
4747                             fun double(myInt: Int) = 2 * myInt
4748                             fun print(foo: Foo = Foo()) { println(foo) }
4749                         }
4750                     }
4751                     """
4752                     ),
4753                     java(
4754                         """
4755                     package some.other.pkg;
4756                     public class Constants {
4757                         public static class Misc {
4758                             public static final int SIZE = 5;
4759                         }
4760                     }
4761                     """
4762                     )
4763                 ),
4764             api =
4765                 """
4766                 // Signature format: 4.0
4767                 package test.pkg {
4768                   public final class Foo {
4769                     ctor public Foo(optional String a, optional String b);
4770                     method public android.graphics.Bitmap? drawToBitmap(android.view.View, optional android.graphics.Bitmap.Config config);
4771                     method public void emptyLambda(optional kotlin.jvm.functions.Function0<kotlin.Unit> sizeOf);
4772                     method public void method1(optional int myInt, optional Integer? myInt2, optional int myByte, optional String str, java.lang.String... args);
4773                     method public void method2(int myInt, optional int myInt2);
4774                     method public void method3(String str, int myInt, optional int myInt2);
4775                     field public static final test.pkg.Foo.Companion Companion;
4776                   }
4777                   public static final class Foo.Companion {
4778                     method public int double(int myInt);
4779                     method public void print(optional test.pkg.Foo foo);
4780                   }
4781                 }
4782                 """,
4783             extraArguments =
4784                 arrayOf(
4785                     ARG_HIDE_PACKAGE,
4786                     "androidx.annotation",
4787                     ARG_HIDE_PACKAGE,
4788                     "some.other.pkg"
4789                 ),
4790         )
4791     }
4792 
4793     @RequiresCapabilities(Capability.KOTLIN)
4794     @Test
Concise default Values in Kotlin for expressionsnull4795     fun `Concise default Values in Kotlin for expressions`() {
4796         // Testing trickier default values; regression test for problem
4797         // observed in androidx.core.util with LruCache
4798         check(
4799             format = FileFormat.V4,
4800             sourceFiles =
4801                 arrayOf(
4802                     kotlin(
4803                         """
4804                     package androidx.core.util
4805 
4806                     import android.util.LruCache
4807 
4808                     inline fun <K : Any, V : Any> lruCache(
4809                         maxSize: Int,
4810                         crossinline sizeOf: (key: K, value: V) -> Int = { _, _ -> 1 },
4811                         @Suppress("USELESS_CAST") // https://youtrack.jetbrains.com/issue/KT-21946
4812                         crossinline create: (key: K) -> V? = { null as V? },
4813                         crossinline onEntryRemoved: (evicted: Boolean, key: K, oldValue: V, newValue: V?) -> Unit =
4814                             { _, _, _, _ -> }
4815                     ): LruCache<K, V> {
4816                         return object : LruCache<K, V>(maxSize) {
4817                             override fun sizeOf(key: K, value: V) = sizeOf(key, value)
4818                             override fun create(key: K) = create(key)
4819                             override fun entryRemoved(evicted: Boolean, key: K, oldValue: V, newValue: V?) {
4820                                 onEntryRemoved(evicted, key, oldValue, newValue)
4821                             }
4822                         }
4823                     }
4824                     """
4825                     ),
4826                     java(
4827                         """
4828                     package androidx.collection;
4829 
4830                     import androidx.annotation.NonNull;
4831                     import androidx.annotation.Nullable;
4832 
4833                     import java.util.LinkedHashMap;
4834                     import java.util.Locale;
4835                     import java.util.Map;
4836 
4837                     public class LruCache<K, V> {
4838                         @Nullable
4839                         protected V create(@NonNull K key) {
4840                             return null;
4841                         }
4842 
4843                         protected int sizeOf(@NonNull K key, @NonNull V value) {
4844                             return 1;
4845                         }
4846 
4847                         protected void entryRemoved(boolean evicted, @NonNull K key, @NonNull V oldValue,
4848                                 @Nullable V newValue) {
4849                         }
4850                     }
4851                     """
4852                     ),
4853                     androidxNullableSource,
4854                     androidxNonNullSource
4855                 ),
4856             api =
4857                 """
4858                 // Signature format: 4.0
4859                 package androidx.core.util {
4860                   public final class TestKt {
4861                     method public static inline <K, V> android.util.LruCache<K,V> lruCache(int maxSize, optional kotlin.jvm.functions.Function2<? super K,? super V,java.lang.Integer> sizeOf, optional kotlin.jvm.functions.Function1<? super K,? extends V?> create, optional kotlin.jvm.functions.Function4<? super java.lang.Boolean,? super K,? super V,? super V?,kotlin.Unit> onEntryRemoved);
4862                   }
4863                 }
4864                 """,
4865             extraArguments =
4866                 arrayOf(
4867                     ARG_HIDE_PACKAGE,
4868                     "androidx.annotation",
4869                     ARG_HIDE_PACKAGE,
4870                     "androidx.collection"
4871                 ),
4872         )
4873     }
4874 
4875     @Test
Test type erasure and dexApi from signaturenull4876     fun `Test type erasure and dexApi from signature`() {
4877         check(
4878             signatureSources =
4879                 arrayOf(
4880                     """
4881                 package android.widget {
4882 
4883                   @android.widget.RemoteViews.RemoteView public class ListView extends android.widget.AbsListView {
4884                     method protected <T extends android.view.View> T findViewTraversal(@IdRes int);
4885                     method protected long tryAcquireShared(long);
4886                   }
4887 
4888                 }
4889                 """
4890                 ),
4891             dexApi =
4892                 """
4893             Landroid/widget/ListView;
4894             Landroid/widget/ListView;->findViewTraversal(I)Landroid/view/View;
4895             Landroid/widget/ListView;->tryAcquireShared(J)J
4896             """
4897         )
4898     }
4899 
4900     @RequiresCapabilities(Capability.KOTLIN)
4901     @Test
Functional interface in signaturenull4902     fun `Functional interface in signature`() {
4903         check(
4904             format = FileFormat.V4,
4905             sourceFiles =
4906                 arrayOf(
4907                     kotlin(
4908                         """
4909                     package test.pkg
4910 
4911                     fun interface FunctionalInterface {
4912                         fun methodOne(number: Int): Boolean
4913                     }
4914 
4915                     fun userOfFunctionalInterface(parameter: FunctionalInterface) { }
4916                 """
4917                     )
4918                 ),
4919             api =
4920                 """
4921                 // Signature format: 4.0
4922                 package test.pkg {
4923                   public fun interface FunctionalInterface {
4924                     method public boolean methodOne(int number);
4925                   }
4926                   public final class FunctionalInterfaceKt {
4927                     method public static void userOfFunctionalInterface(test.pkg.FunctionalInterface parameter);
4928                   }
4929                 }
4930             """
4931         )
4932     }
4933 
4934     @RequiresCapabilities(Capability.KOTLIN)
4935     @Test
Inline classnull4936     fun `Inline class`() {
4937         check(
4938             format = FileFormat.V4,
4939             sourceFiles =
4940                 arrayOf(
4941                     kotlin(
4942                         """
4943                     package test.pkg
4944 
4945                     inline class Dp(val value: Float) : Comparable<Dp> {
4946                         inline operator fun plus(other: Dp) = Dp(value = this.value + other.value)
4947                         inline operator fun minus(other: Dp) = Dp(value = this.value - other.value)
4948                         // Not tracked due to https://youtrack.jetbrains.com/issue/KTIJ-11559
4949                         val someBits
4950                             get() = value.toInt() and 0x00ff
4951                         fun doSomething() {}
4952                     }
4953                 """
4954                     )
4955                 ),
4956             api =
4957                 """
4958                 // Signature format: 4.0
4959                 package test.pkg {
4960                   public final inline class Dp implements java.lang.Comparable<test.pkg.Dp> {
4961                     ctor public Dp();
4962                     method public void doSomething();
4963                     method public float getValue();
4964                     method public inline operator float minus(float other);
4965                     method public inline operator float plus(float other);
4966                     property public final float value;
4967                   }
4968                 }
4969             """
4970         )
4971     }
4972 
4973     @RequiresCapabilities(Capability.KOTLIN)
4974     @Test
Value classnull4975     fun `Value class`() {
4976         check(
4977             format = FileFormat.V4,
4978             sourceFiles =
4979                 arrayOf(
4980                     kotlin(
4981                         """
4982                     package test.pkg
4983                     @JvmInline
4984                     value class Dp(val value: Float) : Comparable<Dp> {
4985                         inline operator fun plus(other: Dp) = Dp(value = this.value + other.value)
4986                         inline operator fun minus(other: Dp) = Dp(value = this.value - other.value)
4987                         val someBits
4988                             get() = value.toInt() and 0x00ff
4989                         fun doSomething() {}
4990                         override fun compareTo(other: Dp): Int = value.compareTo(other.value)
4991                     }
4992 
4993                     fun box(p : Dp) {
4994                         println(p)
4995                     }
4996                 """
4997                     )
4998                 ),
4999             api =
5000                 """
5001                 // Signature format: 4.0
5002                 package test.pkg {
5003                   @kotlin.jvm.JvmInline public final value class Dp implements java.lang.Comparable<test.pkg.Dp> {
5004                     ctor public Dp(float value);
5005                     method public int compareTo(float other);
5006                     method public void doSomething();
5007                     method public int getSomeBits();
5008                     method public float getValue();
5009                     method public inline operator float minus(float other);
5010                     method public inline operator float plus(float other);
5011                     property public final int someBits;
5012                     property public final float value;
5013                   }
5014                   public final class DpKt {
5015                     method public static void box(float p);
5016                   }
5017                 }
5018             """
5019         )
5020     }
5021 
5022     @RequiresCapabilities(Capability.KOTLIN)
5023     @Test
Kotlin doesn't expand java named constantsnull5024     fun `Kotlin doesn't expand java named constants`() {
5025         check(
5026             format = FileFormat.V3,
5027             sourceFiles =
5028                 arrayOf(
5029                     kotlin(
5030                         """
5031                         package test.pkg
5032                         annotation class Foo(val bar: Long = java.lang.Long.MIN_VALUE)
5033                     """
5034                     )
5035                 ),
5036             api =
5037                 """
5038                 // Signature format: 3.0
5039                 package test.pkg {
5040                   @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) public @interface Foo {
5041                     method public abstract long bar() default java.lang.Long.MIN_VALUE;
5042                     property public abstract long bar;
5043                   }
5044                 }
5045             """
5046         )
5047     }
5048 
5049     @RequiresCapabilities(Capability.KOTLIN)
5050     @Test
5051     fun `Kotlin constructors with JvmOverloads`() {
5052         check(
5053             format = FileFormat.V4,
5054             sourceFiles =
5055                 arrayOf(
5056                     kotlin(
5057                         """
5058                         package test.pkg
5059 
5060                         class AllOptionalJvmOverloads @JvmOverloads constructor(
5061                             private val foo: Int = 0,
5062                             private val bar: Int = 0
5063                         )
5064 
5065                         class AllOptionalNoJvmOverloads(
5066                             private val foo: Int = 0,
5067                             private val bar: Int = 0
5068                         )
5069 
5070                         class SomeOptionalJvmOverloads @JvmOverloads constructor(
5071                             private val p1: Int,
5072                             private val p2: Int = 0,
5073                             private val p3: Int,
5074                             private val p4: Int = 0,
5075                             private val p5: Int
5076                         )
5077 
5078                         class SomeOptionalNoJvmOverloads(
5079                             private val foo: Int,
5080                             private val bar: Int = 0
5081                         )
5082                     """
5083                     )
5084                 ),
5085             api =
5086                 """
5087                 // Signature format: 4.0
5088                 package test.pkg {
5089                   public final class AllOptionalJvmOverloads {
5090                     ctor public AllOptionalJvmOverloads();
5091                     ctor public AllOptionalJvmOverloads(optional int foo);
5092                     ctor public AllOptionalJvmOverloads(optional int foo, optional int bar);
5093                   }
5094                   public final class AllOptionalNoJvmOverloads {
5095                     ctor public AllOptionalNoJvmOverloads(optional int foo, optional int bar);
5096                   }
5097                   public final class SomeOptionalJvmOverloads {
5098                     ctor public SomeOptionalJvmOverloads(int p1, int p3, int p5);
5099                     ctor public SomeOptionalJvmOverloads(int p1, optional int p2, int p3, int p5);
5100                     ctor public SomeOptionalJvmOverloads(int p1, optional int p2, int p3, optional int p4, int p5);
5101                   }
5102                   public final class SomeOptionalNoJvmOverloads {
5103                     ctor public SomeOptionalNoJvmOverloads(int foo, optional int bar);
5104                   }
5105                 }
5106             """
5107         )
5108     }
5109 
5110     @RequiresCapabilities(Capability.KOTLIN)
5111     @Test
5112     fun `Kotlin expect-actual with JvmOverloads`() {
5113         check(
5114             format = FileFormat.V4,
5115             sourceFiles =
5116                 arrayOf(
5117                     kotlin(
5118                         "src/commonMain/test/pkg/Expect.kt",
5119                         """
5120                         package test.pkg
5121 
5122                         expect class AllOptionalJvmOverloads @JvmOverloads constructor(
5123                             private val foo: Int = 0,
5124                             private val bar: Int = 0
5125                         )
5126 
5127                         expect class SomeOptionalJvmOverloads @JvmOverloads constructor(
5128                             private val p1: Int,
5129                             private val p2: Int = 0,
5130                             private val p3: Int,
5131                             private val p4: Int = 0,
5132                             private val p5: Int
5133                         )
5134 
5135                         expect class AllOptionalJvmOverloadsBothSides @JvmOverloads constructor(
5136                             private val foo: Int = 0,
5137                             private val bar: Int = 0
5138                         )
5139                     """
5140                     ),
5141                     kotlin(
5142                         "src/jvmMain/test/pkg/Actual.kt",
5143                         """
5144                         package test.pkg
5145 
5146                         actual class AllOptionalJvmOverloads @JvmOverloads actual constructor(
5147                             private val foo: Int,
5148                             private val bar: Int
5149                         )
5150 
5151                         actual class SomeOptionalJvmOverloads @JvmOverloads actual constructor(
5152                             private val p1: Int,
5153                             private val p2: Int,
5154                             private val p3: Int,
5155                             private val p4: Int,
5156                             private val p5: Int
5157                         )
5158 
5159                         actual class AllOptionalJvmOverloadsBothSides @JvmOverloads actual constructor(
5160                             private val foo: Int = 0,
5161                             private val bar: Int = 0
5162                         )
5163                     """
5164                     )
5165                 ),
5166             api =
5167                 """
5168                     // Signature format: 4.0
5169                     package test.pkg {
5170                       public final class AllOptionalJvmOverloads {
5171                         ctor public AllOptionalJvmOverloads();
5172                         ctor public AllOptionalJvmOverloads(optional int foo);
5173                         ctor public AllOptionalJvmOverloads(optional int foo, optional int bar);
5174                       }
5175                       public final class AllOptionalJvmOverloadsBothSides {
5176                         ctor public AllOptionalJvmOverloadsBothSides();
5177                         ctor public AllOptionalJvmOverloadsBothSides(optional int foo);
5178                         ctor public AllOptionalJvmOverloadsBothSides(optional int foo, optional int bar);
5179                       }
5180                       public final class SomeOptionalJvmOverloads {
5181                         ctor public SomeOptionalJvmOverloads(int p1, int p3, int p5);
5182                         ctor public SomeOptionalJvmOverloads(int p1, optional int p2, int p3, int p5);
5183                         ctor public SomeOptionalJvmOverloads(int p1, optional int p2, int p3, optional int p4, int p5);
5184                       }
5185                     }
5186                 """
5187         )
5188     }
5189 
5190     @RequiresCapabilities(Capability.KOTLIN)
5191     @Test
5192     fun `Kotlin public methods with DeprecationLevel HIDDEN are public API`() {
5193         check(
5194             format = FileFormat.V3,
5195             sourceFiles =
5196                 arrayOf(
5197                     kotlin(
5198                         """
5199                         package test.pkg
5200                         @Deprecated(
5201                             message = "So much regret",
5202                             level = DeprecationLevel.HIDDEN
5203                         )
5204                         fun myMethod() { TODO() }
5205                         @Deprecated(
5206                             message = "So much regret",
5207                             level = DeprecationLevel.HIDDEN
5208                         )
5209                         internal fun myInternalMethod() { TODO() }
5210                         @Deprecated(
5211                             message = "So much regret",
5212                             level = DeprecationLevel.HIDDEN
5213                         )
5214                         private fun myPrivateMethod() { TODO() }
5215                         @Deprecated(
5216                             message = "So much regret",
5217                             level = DeprecationLevel.WARNING
5218                         )
5219                         fun myNormalDeprecatedMethod() { TODO() }
5220                     """
5221                     )
5222                 ),
5223             api =
5224                 """
5225                 // Signature format: 3.0
5226                 package test.pkg {
5227                   public final class TestKt {
5228                     method @Deprecated public static void myMethod();
5229                     method @Deprecated public static void myNormalDeprecatedMethod();
5230                   }
5231                 }
5232             """
5233         )
5234     }
5235 
5236     @RequiresCapabilities(Capability.KOTLIN)
5237     @Test
5238     fun `Annotations aren't dropped when DeprecationLevel is HIDDEN`() {
5239         // Regression test for http://b/219792969
5240         check(
5241             format = FileFormat.V2,
5242             sourceFiles =
5243                 arrayOf(
5244                     kotlin(
5245                         """
5246                         package test.pkg
5247                         import androidx.annotation.IntRange
5248                         @Deprecated(
5249                             message = "So much regret",
5250                             level = DeprecationLevel.HIDDEN
5251                         )
5252                         @IntRange(from=0)
5253                         fun myMethod() { TODO() }
5254 
5255                         @Deprecated(
5256                             message = "Not supported anymore",
5257                             level = DeprecationLevel.HIDDEN
5258                         )
5259                         fun returnsNonNull(): String = "42"
5260 
5261                         @Deprecated(
5262                             message = "Not supported anymore",
5263                             level = DeprecationLevel.HIDDEN
5264                         )
5265                         fun returnsNonNullImplicitly() = "42"
5266                     """
5267                     ),
5268                     androidxIntRangeSource
5269                 ),
5270             extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation"),
5271             api =
5272                 """
5273                 // Signature format: 2.0
5274                 package test.pkg {
5275                   public final class TestKt {
5276                     method @Deprecated @IntRange(from=0L) public static void myMethod();
5277                     method @Deprecated @NonNull public static String returnsNonNull();
5278                     method @Deprecated @NonNull public static String returnsNonNullImplicitly();
5279                   }
5280                 }
5281             """
5282         )
5283     }
5284 
5285     @RequiresCapabilities(Capability.KOTLIN)
5286     @Test
Constants in a file scope annotationnull5287     fun `Constants in a file scope annotation`() {
5288         check(
5289             sourceFiles =
5290                 arrayOf(
5291                     kotlin(
5292                         """
5293                     @file:RestrictTo(RestrictTo.Scope.LIBRARY)
5294                     package test.pkg
5295                     import androidx.annotation.RestrictTo
5296                     private fun veryFun(): Boolean = true
5297                     const val CONST = "Hello"
5298                     fun bar()
5299                 """
5300                     ),
5301                     restrictToSource
5302                 ),
5303             extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation"),
5304             format = FileFormat.V4,
5305             api =
5306                 """
5307                 // Signature format: 4.0
5308                 package test.pkg {
5309                   @RestrictTo({androidx.annotation.RestrictTo.Scope.LIBRARY}) public final class TestKt {
5310                     method public static void bar();
5311                     field public static final String CONST = "Hello";
5312                   }
5313                 }
5314             """
5315         )
5316     }
5317 
5318     @RequiresCapabilities(Capability.KOTLIN)
5319     @Test
RestrictTo on a file hiding itnull5320     fun `RestrictTo on a file hiding it`() {
5321         check(
5322             format = FileFormat.V4,
5323             sourceFiles =
5324                 arrayOf(
5325                     kotlin(
5326                         """
5327                     @file:RestrictTo(RestrictTo.Scope.LIBRARY)
5328                     package test.pkg
5329                     import androidx.annotation.RestrictTo
5330                     private fun veryFun(): Boolean = true
5331                 """
5332                     ),
5333                     restrictToSource
5334                 ),
5335             extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation", "--show-unannotated"),
5336             hideAnnotations =
5337                 arrayOf(
5338                     "androidx.annotation.RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY)"
5339                 ),
5340             api = """
5341                 // Signature format: 4.0
5342             """
5343         )
5344     }
5345 
5346     /** Regression test for b/202968090 */
5347     @RequiresCapabilities(Capability.KOTLIN)
5348     @Test
annotation arrays should be non-nullnull5349     fun `annotation arrays should be non-null`() {
5350         check(
5351             format = FileFormat.V4,
5352             sourceFiles =
5353                 arrayOf(
5354                     kotlin(
5355                         """
5356                         package test.pkg
5357                         annotation class Foo (
5358                             val bar: Array<String>,
5359                             vararg val baz: String
5360                         )
5361                     """
5362                     )
5363                 ),
5364             api =
5365                 """
5366                 // Signature format: 4.0
5367                 package test.pkg {
5368                   @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) public @interface Foo {
5369                     method public abstract String[] bar();
5370                     method public abstract String[] baz();
5371                     property public abstract String[] bar;
5372                     property public abstract String[] baz;
5373                   }
5374                 }
5375             """
5376         )
5377     }
5378 
5379     @RequiresCapabilities(Capability.KOTLIN)
5380     @Test
property setter parameters are unnamednull5381     fun `property setter parameters are unnamed`() {
5382         check(
5383             sourceFiles =
5384                 arrayOf(
5385                     kotlin(
5386                         """
5387                         package test.pkg
5388                         class Foo(var bar: Int)
5389                     """
5390                     )
5391                 ),
5392             api =
5393                 """
5394                 package test.pkg {
5395                   public final class Foo {
5396                     ctor public Foo(int bar);
5397                     method public int getBar();
5398                     method public void setBar(int);
5399                     property public final int bar;
5400                   }
5401                 }
5402             """
5403         )
5404     }
5405 
5406     @RequiresCapabilities(Capability.KOTLIN)
5407     @Test
implements kotlin collectionnull5408     fun `implements kotlin collection`() {
5409         check(
5410             sourceFiles =
5411                 arrayOf(
5412                     kotlin(
5413                         """
5414                         package test.pkg
5415                         class MyList : List<String> {
5416                           override operator fun get(index: Int): String {}
5417                         }
5418                     """
5419                     )
5420                 ),
5421             api =
5422                 """
5423                 package test.pkg {
5424                   public final class MyList implements kotlin.jvm.internal.markers.KMappedMarker java.util.List<java.lang.String> {
5425                     ctor public MyList();
5426                     method public operator String get(int index);
5427                   }
5428                 }
5429             """
5430         )
5431     }
5432 
5433     @RequiresCapabilities(Capability.KOTLIN)
5434     @Test
companion object in annotationnull5435     fun `companion object in annotation`() {
5436         check(
5437             sourceFiles =
5438                 arrayOf(
5439                     kotlin(
5440                         """
5441                         package test.pkg
5442                         annotation class Dimension(val unit: Int = PX) {
5443                             companion object {
5444                                 const val DP: Int = 0
5445                                 const val PX: Int = 1
5446                                 const val SP: Int = 2
5447                             }
5448                         }
5449                     """
5450                     )
5451                 ),
5452             api =
5453                 """
5454                 package test.pkg {
5455                   @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) public @interface Dimension {
5456                     method public abstract int unit() default test.pkg.Dimension.PX;
5457                     property public abstract int unit;
5458                     field public static final test.pkg.Dimension.Companion Companion;
5459                     field public static final int DP = 0; // 0x0
5460                     field public static final int PX = 1; // 0x1
5461                     field public static final int SP = 2; // 0x2
5462                   }
5463                   public static final class Dimension.Companion {
5464                     field public static final int DP = 0; // 0x0
5465                     field public static final int PX = 1; // 0x1
5466                     field public static final int SP = 2; // 0x2
5467                   }
5468                 }
5469             """
5470         )
5471     }
5472 
5473     @RequiresCapabilities(Capability.KOTLIN)
5474     @Test
APIs before and after @Deprecated(HIDDEN)null5475     fun `APIs before and after @Deprecated(HIDDEN)`() {
5476         val sameModifiersAndReturnType = "public static test.pkg.State<java.lang.String>"
5477         val sameParameters = "(Integer? i, String? s, java.lang.Object... vs);"
5478         check(
5479             sourceFiles =
5480                 arrayOf(
5481                     kotlin(
5482                         """
5483                         package test.pkg
5484                         interface State<out T> {
5485                             val value: T
5486                         }
5487 
5488                         @Deprecated(level = DeprecationLevel.HIDDEN, message="no longer supported")
5489                         fun before(
5490                             i : Int?,
5491                             s : String?,
5492                             vararg vs : Any,
5493                         ): State<String> {
5494                             return object : State<String> {
5495                                 override val value: String = i?.toString() ?: s ?: "42"
5496                             }
5497                         }
5498 
5499                         fun after(
5500                             i : Int?,
5501                             s : String?,
5502                             vararg vs : Any,
5503                         ): State<String> {
5504                             return object : State<String> {
5505                                 override val value: String = i?.toString() ?: s ?: "42"
5506                             }
5507                         }
5508                     """
5509                     )
5510                 ),
5511             api =
5512                 """
5513                 package test.pkg {
5514                   public interface State<T> {
5515                     method public T getValue();
5516                     property public abstract T value;
5517                   }
5518                   public final class StateKt {
5519                     method $sameModifiersAndReturnType after$sameParameters
5520                     method @Deprecated $sameModifiersAndReturnType before$sameParameters
5521                   }
5522                 }
5523             """
5524         )
5525     }
5526 
5527     @RequiresCapabilities(Capability.KOTLIN)
5528     @Test
APIs before and after @Deprecated(HIDDEN) on constructorsnull5529     fun `APIs before and after @Deprecated(HIDDEN) on constructors`() {
5530         check(
5531             sourceFiles =
5532                 arrayOf(
5533                     kotlin(
5534                         """
5535                         package test.pkg
5536                         interface State<out T> {
5537                             val value: T
5538                         }
5539 
5540                         class AsyncPagingDataDiffer<T : Any>
5541                         @JvmOverloads
5542                         constructor(
5543                             private val initState: State<T>,
5544                             private val nextState: State<T>,
5545                             private val updateCallback: Runnable,
5546                         ) {
5547                             @Deprecated(level = DeprecationLevel.HIDDEN, message="no longer supported")
5548                             constructor(
5549                                 state: State<T>,
5550                             ) : this(
5551                                 initState = state,
5552                                 nextState = state,
5553                                 updateCallback = { }
5554                             )
5555 
5556                             constructor(
5557                                 initState: State<T>,
5558                                 nextState: State<T>,
5559                             ) : this(
5560                                 initState = initState,
5561                                 nextState = nextState,
5562                                 updateCallback = { }
5563                             )
5564                         }
5565                     """
5566                     )
5567                 ),
5568             api =
5569                 """
5570                 package test.pkg {
5571                   public final class AsyncPagingDataDiffer<T> {
5572                     ctor @Deprecated public AsyncPagingDataDiffer(test.pkg.State<? extends T> state);
5573                     ctor public AsyncPagingDataDiffer(test.pkg.State<? extends T> initState, test.pkg.State<? extends T> nextState);
5574                     ctor public AsyncPagingDataDiffer(test.pkg.State<? extends T> initState, test.pkg.State<? extends T> nextState, Runnable updateCallback);
5575                   }
5576                   public interface State<T> {
5577                     method public T getValue();
5578                     property public abstract T value;
5579                   }
5580                 }
5581             """
5582         )
5583     }
5584 
5585     @RequiresCapabilities(Capability.KOTLIN)
5586     @Test
@Deprecated sealed interface and its membersnull5587     fun `@Deprecated sealed interface and its members`() {
5588         check(
5589             sourceFiles =
5590                 arrayOf(
5591                     kotlin(
5592                         """
5593                         package test.pkg
5594 
5595                         @Deprecated("moved to somewhere else")
5596                         sealed interface LazyInfo {
5597                           val index : Int
5598                           val key: Int
5599                         }
5600                     """
5601                     )
5602                 ),
5603             api =
5604                 """
5605                 package test.pkg {
5606                   @Deprecated public sealed interface LazyInfo {
5607                     method @Deprecated public int getIndex();
5608                     method @Deprecated public int getKey();
5609                     property @Deprecated public abstract int index;
5610                     property @Deprecated public abstract int key;
5611                   }
5612                 }
5613             """
5614         )
5615     }
5616 
5617     @RequiresCapabilities(Capability.KOTLIN)
5618     @Test
@Repeatable annotationnull5619     fun `@Repeatable annotation`() {
5620         check(
5621             sourceFiles =
5622                 arrayOf(
5623                     kotlin(
5624                         """
5625                     package test.pkg
5626 
5627                     import androidx.annotation.IntRange
5628 
5629                     @Repeatable
5630                     annotation class RequiresExtension(
5631                         @IntRange(from = 1) val extension: Int,
5632                         @IntRange(from = 1) val version: Int
5633                     )
5634                     """
5635                     ),
5636                     androidxIntRangeSource
5637                 ),
5638             extraArguments = arrayOf(ARG_HIDE_PACKAGE, "androidx.annotation"),
5639             api =
5640                 """
5641                 package test.pkg {
5642                   @kotlin.annotation.Repeatable public @interface RequiresExtension {
5643                     method public abstract int extension();
5644                     method public abstract int version();
5645                     property public abstract int extension;
5646                     property public abstract int version;
5647                   }
5648                   @kotlin.annotation.Repeatable public static @interface RequiresExtension.Container {
5649                     method public abstract test.pkg.RequiresExtension[] value();
5650                   }
5651                 }
5652             """
5653         )
5654     }
5655 
5656     @RequiresCapabilities(Capability.KOTLIN)
5657     @Test
Don't print empty facade classesnull5658     fun `Don't print empty facade classes`() {
5659         check(
5660             sourceFiles =
5661                 arrayOf(
5662                     kotlin(
5663                         "test/pkg/Toast.kt",
5664                         """
5665                         package test.pkg
5666                         internal fun bar() {}
5667 
5668                         private val baz
5669 
5670                         class Toast {
5671                             val foo: Int
5672                         }
5673                     """
5674                     ),
5675                     kotlin(
5676                         "test/pkg/Bar.kt",
5677                         """
5678                         package test.pkg
5679                         class Bar
5680                     """
5681                     ),
5682                     kotlin(
5683                         "test/pkg/test.kt",
5684                         """
5685                         package test.pkg
5686 
5687                         /**
5688                          * @suppress
5689                          */
5690                         @PublishedApi
5691                         internal fun internalYetPublished() {}
5692 
5693                         private val buzz
5694                     """
5695                     ),
5696                     kotlin(
5697                         "test/pkg/ConfigurationError.kt",
5698                         """
5699                         package test.pkg
5700                         import androidx.annotation.RestrictTo
5701 
5702                         /**
5703                          * @hide
5704                          */
5705                         @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
5706                         data class ConfigurationError(val id: String)
5707 
5708                         /**
5709                          * @hide
5710                          */
5711                         @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
5712                         fun conditionalError(): ConfigurationError? = null
5713                     """
5714                     ),
5715                     kotlin(
5716                         "test/pkg/test2.kt",
5717                         """
5718                         package test.pkg
5719                         import androidx.annotation.VisibleForTesting
5720 
5721                         @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
5722                         fun shouldBePackagePrivate() {}
5723 
5724                         private fun shouldBePrivate() {}
5725                     """
5726                     ),
5727                     kotlin(
5728                         "test/pkg/Path1.kt",
5729                         """
5730                         package test.pkg
5731 
5732                         expect fun Path1(): Path1
5733 
5734                         interface Path1 {
5735                           infix fun xor(path: Path1): Path1
5736                         }
5737                     """
5738                     ),
5739                     kotlin(
5740                         "test/pkg/Path2.kt",
5741                         """
5742                         package test.pkg
5743 
5744                         expect fun Path2(): Path2
5745 
5746                         fun Path2.copy(): Path2 = TODO()
5747 
5748                         interface Path2 {
5749                           infix fun xor(path: Path2): Path2
5750                         }
5751                     """
5752                     ),
5753                     kotlin(
5754                         "test/pkg/LazyLayoutItemProvider.kt",
5755                         """
5756                         package test.pkg
5757 
5758                         interface LazyLayoutItemProvider {
5759                           val itemCount: Int
5760                           fun getIndex(): Int = -1
5761                         }
5762 
5763                         internal fun LazyLayoutItemProvider.findIndexByKey(
5764                           key: Any?,
5765                           lastKnownIndex: Int,
5766                         ): Int = TODO()
5767 
5768                         expect fun getDefaultLazyLayoutKey(index: Int): Any
5769                         """
5770                     ),
5771                     restrictToSource,
5772                     visibleForTestingSource,
5773                 ),
5774             extraArguments =
5775                 arrayOf(
5776                     ARG_SHOW_UNANNOTATED,
5777                     ARG_SHOW_ANNOTATION,
5778                     "kotlin.PublishedApi",
5779                     ARG_HIDE_ANNOTATION,
5780                     "androidx.annotation.RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP)",
5781                     ARG_HIDE_PACKAGE,
5782                     "androidx.annotation"
5783                 ),
5784             format = FileFormat.V4,
5785             api =
5786                 """
5787                 // Signature format: 4.0
5788                 package test.pkg {
5789                   public final class Bar {
5790                     ctor public Bar();
5791                   }
5792                   public interface LazyLayoutItemProvider {
5793                     method public default int getIndex();
5794                     method public int getItemCount();
5795                     property public abstract int itemCount;
5796                   }
5797                   public interface Path1 {
5798                     method public infix test.pkg.Path1 xor(test.pkg.Path1 path);
5799                   }
5800                   public interface Path2 {
5801                     method public infix test.pkg.Path2 xor(test.pkg.Path2 path);
5802                   }
5803                   public final class Path2Kt {
5804                     method public static test.pkg.Path2 copy(test.pkg.Path2);
5805                   }
5806                   public final class TestKt {
5807                     method @kotlin.PublishedApi internal static void internalYetPublished();
5808                   }
5809                   public final class Toast {
5810                     ctor public Toast();
5811                     method public int getFoo();
5812                     property public final int foo;
5813                   }
5814                 }
5815             """
5816         )
5817     }
5818 
5819     @RequiresCapabilities(Capability.KOTLIN)
5820     @Test
5821     fun `Test @JvmMultifileClass appears only once`() {
5822         check(
5823             sourceFiles =
5824                 arrayOf(
5825                     kotlin(
5826                         "test/pkg/A.kt",
5827                         """
5828                         @file:JvmMultifileClass
5829                         @file:JvmName("Foo")
5830 
5831                         package test.pkg
5832 
5833                         fun String.bar(): Unit {}
5834                     """
5835                     ),
5836                     kotlin(
5837                         "test/pkg/B.kt",
5838                         """
5839                         @file:JvmMultifileClass
5840                         @file:JvmName("Foo")
5841 
5842                         package test.pkg
5843 
5844                         fun String.baz(): Unit {}
5845                     """
5846                     )
5847                 ),
5848             format = FileFormat.V4,
5849             api =
5850                 """
5851                 // Signature format: 4.0
5852                 package test.pkg {
5853                   public final class Foo {
5854                     method public static void bar(String);
5855                     method public static void baz(String);
5856                   }
5857                 }
5858             """
5859         )
5860     }
5861 
5862     @RequiresCapabilities(Capability.KOTLIN)
5863     @Test
5864     fun `@JvmName on @Deprecated hidden`() {
5865         check(
5866             sourceFiles =
5867                 arrayOf(
5868                     kotlin(
5869                         """
5870                         package test.pkg
5871                         class Foo {
5872                           @JvmName("newNameForRenamed")
5873                           fun renamed() = Unit
5874 
5875                           @Deprecated(level = DeprecationLevel.HIDDEN)
5876                           fun deprecatedHidden() = Unit
5877 
5878                           @JvmName("newNameForRenamedAndDeprecatedError")
5879                           @Deprecated(level = DeprecationLevel.ERROR)
5880                           fun renamedAndDeprecatedError() = Unit
5881 
5882                           @JvmName("newNameForRenamedAndDeprecatedHidden")
5883                           @Deprecated(level = DeprecationLevel.HIDDEN)
5884                           fun renamedAndDeprecatedHidden() = Unit
5885                         }
5886                     """
5887                     )
5888                 ),
5889             api =
5890                 """
5891                package test.pkg {
5892                  public final class Foo {
5893                    ctor public Foo();
5894                    method @Deprecated public void deprecatedHidden();
5895                    method public void newNameForRenamed();
5896                    method @Deprecated public void newNameForRenamedAndDeprecatedError();
5897                    method @Deprecated public void newNameForRenamedAndDeprecatedHidden();
5898                  }
5899                }
5900             """
5901         )
5902     }
5903 
5904     @RequiresCapabilities(Capability.KOTLIN)
5905     @Test
5906     fun `Ordering of methods`() {
5907         check(
5908             sourceFiles =
5909                 arrayOf(
5910                     kotlin(
5911                         """
5912                         package test.pkg
5913 
5914                         class Foo {
5915                             fun foo(s: String) {}
5916                             fun foo(i: Int) {}
5917                         }
5918 
5919                         class Bar {
5920                             fun bar(i: Int) {}
5921                             fun bar(s: String) {}
5922                         }
5923                     """
5924                     )
5925                 ),
5926             api =
5927                 """
5928                 package test.pkg {
5929                   public final class Bar {
5930                     ctor public Bar();
5931                     method public void bar(int i);
5932                     method public void bar(String s);
5933                   }
5934                   public final class Foo {
5935                     ctor public Foo();
5936                     method public void foo(int i);
5937                     method public void foo(String s);
5938                   }
5939                 }
5940             """
5941         )
5942     }
5943 
5944     @Test
5945     fun `Partial signature files include affected subclass definitions`() {
5946         check(
5947             format = FileFormat.V2,
5948             sourceFiles =
5949                 arrayOf(
5950                     java(
5951                         """
5952                         package test.pkg;
5953 
5954                         public class SomePublicClass {
5955                         }
5956                     """
5957                     ),
5958                     java(
5959                         """
5960                         package test.pkg;
5961 
5962                         import android.annotation.SystemApi;
5963 
5964                         /** @hide */
5965                         @SystemApi
5966                         public class SystemSubClass extends SomePublicClass {
5967                         }
5968                     """
5969                     ),
5970                     java(
5971                         """
5972                         package test.pkg;
5973 
5974                         public class AnotherPublicClass extends SystemSubClass {
5975                         }
5976                     """
5977                     ),
5978                     systemApiSource
5979                 ),
5980             api =
5981                 """
5982                 // Signature format: 2.0
5983                 package test.pkg {
5984                   public class AnotherPublicClass extends test.pkg.SystemSubClass {
5985                   }
5986                   public class SystemSubClass extends test.pkg.SomePublicClass {
5987                     ctor public SystemSubClass();
5988                   }
5989                 }
5990             """,
5991             extraArguments =
5992                 arrayOf(
5993                     ARG_SHOW_ANNOTATION,
5994                     "android.annotation.SystemApi",
5995                     ARG_HIDE_PACKAGE,
5996                     "android.annotation",
5997                 )
5998         )
5999     }
6000 
6001     @Test
6002     fun `Partial signature files include affected subclass definitions in complex class hierarchy`() {
6003         check(
6004             format = FileFormat.V2,
6005             sourceFiles =
6006                 arrayOf(
6007                     java(
6008                         """
6009                         package test.pkg;
6010 
6011                         public class SomePublicClass {
6012                         }
6013                     """
6014                     ),
6015                     java(
6016                         """
6017                         package test.pkg;
6018 
6019                         import android.annotation.SystemApi;
6020 
6021                         /** @hide */
6022                         @SystemApi
6023                         public class SystemSubClass extends SomePublicClass {
6024                         }
6025                     """
6026                     ),
6027                     java(
6028                         """
6029                         package test.pkg;
6030 
6031                         import android.annotation.TestApi;
6032 
6033                         /** @hide */
6034                         @TestApi
6035                         public class TestSubClass extends SystemSubClass {
6036                         }
6037                     """
6038                     ),
6039                     java(
6040                         """
6041                         package test.pkg;
6042 
6043                         import android.annotation.SystemApi;
6044 
6045                         /** @hide */
6046                         @SystemApi
6047                         public class AnotherSystemSubClass extends TestSubClass {
6048                         }
6049                     """
6050                     ),
6051                     java(
6052                         """
6053                         package test.pkg;
6054 
6055                         import android.annotation.TestApi;
6056 
6057                         /** @hide */
6058                         @TestApi
6059                         public class AnotherTestSubClass extends AnotherSystemSubClass {
6060                         }
6061                     """
6062                     ),
6063                     java(
6064                         """
6065                         package test.pkg;
6066 
6067                         public class AnotherPublicClass extends AnotherTestSubClass {
6068                         }
6069                     """
6070                     ),
6071                     systemApiSource,
6072                     testApiSource,
6073                 ),
6074             api =
6075                 """
6076                 // Signature format: 2.0
6077                 package test.pkg {
6078                   public class AnotherPublicClass extends test.pkg.AnotherTestSubClass {
6079                   }
6080                   public class AnotherTestSubClass extends test.pkg.AnotherSystemSubClass {
6081                     ctor public AnotherTestSubClass();
6082                   }
6083                   public class TestSubClass extends test.pkg.SystemSubClass {
6084                     ctor public TestSubClass();
6085                   }
6086                 }
6087             """,
6088             extraArguments =
6089                 arrayOf(
6090                     ARG_SHOW_ANNOTATION,
6091                     "android.annotation.TestApi",
6092                     ARG_HIDE_PACKAGE,
6093                     "android.annotation",
6094                     ARG_SHOW_FOR_STUB_PURPOSES_ANNOTATION,
6095                     "android.annotation.SystemApi",
6096                 )
6097         )
6098     }
6099 
6100     @Test
6101     fun `Subclass definition is not included in removed api file`() {
6102         check(
6103             format = FileFormat.V2,
6104             expectedIssues =
6105                 """
6106                 src/test/pkg/AnotherPublicClass.java:3: warning: Public class test.pkg.AnotherPublicClass stripped of unavailable superclass test.pkg.SystemSubClass [HiddenSuperclass]
6107             """,
6108             sourceFiles =
6109                 arrayOf(
6110                     java(
6111                         """
6112                         package test.pkg;
6113 
6114                         public class SomePublicClass {
6115                         }
6116                     """
6117                     ),
6118                     java(
6119                         """
6120                         package test.pkg;
6121 
6122                         import android.annotation.SystemApi;
6123 
6124                         /**
6125                          * @hide
6126                          * @removed
6127                          */
6128                         @SystemApi
6129                         public class SystemSubClass extends SomePublicClass {
6130                         }
6131                     """
6132                     ),
6133                     java(
6134                         """
6135                         package test.pkg;
6136 
6137                         public class AnotherPublicClass extends SystemSubClass {
6138                         }
6139                     """
6140                     ),
6141                     systemApiSource
6142                 ),
6143             removedApi =
6144                 """
6145                 // Signature format: 2.0
6146                 package test.pkg {
6147                   public class SystemSubClass extends test.pkg.SomePublicClass {
6148                     ctor public SystemSubClass();
6149                   }
6150                 }
6151             """,
6152             extraArguments =
6153                 arrayOf(
6154                     ARG_SHOW_ANNOTATION,
6155                     "android.annotation.SystemApi",
6156                     ARG_HIDE_PACKAGE,
6157                     "android.annotation",
6158                 )
6159         )
6160     }
6161 
6162     @Test
6163     fun `Type-use annotations can be included in signature files`() {
6164         check(
6165             sourceFiles =
6166                 arrayOf(
6167                     java(
6168                         """
6169                             package test.pkg;
6170                             @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE)
6171                             public @interface TypeAnnotation {}
6172                         """
6173                     ),
6174                     java(
6175                         """
6176                             package test.pkg;
6177                             @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD)
6178                             public @interface MethodAnnotation {}
6179                         """
6180                     ),
6181                     java(
6182                         """
6183                             package test.pkg;
6184                             @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.TYPE_USE})
6185                             public @interface MethodAndTypeAnnotation {}
6186                         """
6187                     ),
6188                     java(
6189                         """
6190                             package test.pkg;
6191                             import java.util.List;
6192                             public class Foo {
6193                                 @MethodAnnotation
6194                                 @MethodAndTypeAnnotation
6195                                 public @TypeAnnotation List<@TypeAnnotation String> foo() {}
6196                             }
6197                         """
6198                     )
6199                 ),
6200             format =
6201                 FileFormat.V5.copy(kotlinNameTypeOrder = true, includeTypeUseAnnotations = true),
6202             api =
6203                 """
6204                     package test.pkg {
6205                       public class Foo {
6206                         ctor public Foo();
6207                         method @test.pkg.MethodAndTypeAnnotation @test.pkg.MethodAnnotation public foo(): java.util.@test.pkg.MethodAndTypeAnnotation @test.pkg.TypeAnnotation List<java.lang.@test.pkg.TypeAnnotation String!>!;
6208                       }
6209                       @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.TYPE_USE}) public @interface MethodAndTypeAnnotation {
6210                       }
6211                       @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) public @interface MethodAnnotation {
6212                       }
6213                       @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) public @interface TypeAnnotation {
6214                       }
6215                     }
6216                 """
6217         )
6218     }
6219 
6220     @RequiresCapabilities(Capability.KOTLIN)
6221     @Test
6222     fun `Test signature including parameterized converted type`() {
6223         check(
6224             sourceFiles =
6225                 arrayOf(
6226                     java(
6227                         """
6228                             package test.pkg;
6229                             public interface VisibleInterface<V> {}
6230                         """
6231                     ),
6232                     java(
6233                         """
6234                             package test.pkg;
6235                             import androidx.annotation.RestrictTo;
6236                             @RestrictTo(RestrictTo.Scope.LIBRARY)
6237                             public interface HiddenInterface<H> extends VisibleInterface<H> {}
6238                         """
6239                     ),
6240                     java(
6241                         """
6242                             package test.pkg;
6243                             import java.util.List;
6244                             public class Foo<F> implements HiddenInterface<List<F>> {}
6245                         """
6246                     ),
6247                     restrictToSource
6248                 ),
6249             // When `HiddenInterface` is hidden, the implements clause for `Foo` is converted to
6250             // `VisibleInterface` using [ClassItem.mapTypeVariables]. It really should become
6251             // `implements test.pkg.VisibleInterface<java.util.List<F>>`, but the `F` is erased from
6252             // `List` for legacy reasons.
6253             api =
6254                 """
6255                     // Signature format: 5.0
6256                     package test.pkg {
6257                       public class Foo<F> implements test.pkg.VisibleInterface<java.util.List!> {
6258                         ctor public Foo();
6259                       }
6260                       public interface VisibleInterface<V> {
6261                       }
6262                     }
6263                 """,
6264             skipEmitPackages = listOf("androidx.annotation"),
6265             hideAnnotations = arrayOf("androidx.annotation.RestrictTo"),
6266             expectedIssues =
6267                 "src/test/pkg/Foo.java:3: warning: Public class test.pkg.Foo stripped of unavailable superclass test.pkg.HiddenInterface [HiddenSuperclass]"
6268         )
6269     }
6270 
6271     @RequiresCapabilities(Capability.KOTLIN)
6272     @Test
6273     fun `sealed class with internal setter`() {
6274         check(
6275             sourceFiles =
6276                 arrayOf(
6277                     kotlin(
6278                         """
6279                             package test.pkg
6280 
6281                             sealed class TransitionState<S> {
6282                               abstract var currentState: S
6283                                 internal set
6284                             }
6285 
6286                             class SeekableTransitionState<S>(
6287                                 initialState: S
6288                             ) : TransitionState<S>() {
6289                               override var currentState: S = initialState
6290                                 internal set
6291                             }
6292                         """
6293                     )
6294                 ),
6295             api =
6296                 """
6297                 // Signature format: 5.0
6298                 package test.pkg {
6299                   public final class SeekableTransitionState<S> extends test.pkg.TransitionState<S> {
6300                     ctor public SeekableTransitionState(S initialState);
6301                     method public S getCurrentState();
6302                     property public S currentState;
6303                   }
6304                   public abstract sealed class TransitionState<S> {
6305                     method public abstract S getCurrentState();
6306                     property public abstract S currentState;
6307                   }
6308                 }
6309                 """
6310         )
6311     }
6312 
6313     @RequiresCapabilities(Capability.KOTLIN)
6314     @Test
6315     fun `Usage of NullableType annotation`() {
6316         check(
6317             sourceFiles =
6318                 arrayOf(
6319                     java(
6320                         """
6321                             package test.pkg;
6322                             import java.util.List;
6323                             public class Foo {
6324                                 public List<@NullableType String> foo(@NullableType Number nullableNumber, Number otherNumber) { return null; }
6325                             }
6326                         """
6327                     ),
6328                     kotlin(
6329                         """
6330                             package test.pkg
6331                             @Target(AnnotationTarget.TYPE)
6332                             annotation class NullableType
6333                         """
6334                     )
6335                 ),
6336             api =
6337                 """
6338                     package test.pkg {
6339                       public class Foo {
6340                         ctor public Foo();
6341                         method public java.util.List<java.lang.String?>! foo(Number?, Number!);
6342                       }
6343                       @kotlin.annotation.Target(allowedTargets=kotlin.annotation.AnnotationTarget.TYPE) public @interface NullableType {
6344                       }
6345                     }
6346                 """
6347         )
6348     }
6349 }
6350