• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package com.android.tools.metalava
18 
19 import org.intellij.lang.annotations.Language
20 import org.junit.Test
21 
22 class ApiFromTextTest : DriverTest() {
23 
24     @Test
Loading a signature file and writing the API back outnull25     fun `Loading a signature file and writing the API back out`() {
26         val source = """
27                 package test.pkg {
28                   public class MyTest {
29                     ctor public MyTest();
30                     method public int clamp(int);
31                     method public Double convert(Float);
32                     field public static final String ANY_CURSOR_ITEM_TYPE = "vnd.android.cursor.item/*";
33                     field public Number myNumber;
34                   }
35                 }
36                 """
37 
38         check(
39             format = FileFormat.V2,
40             signatureSource = source,
41             api = source
42         )
43     }
44 
45     @Test
Handle lambdas as default valuesnull46     fun `Handle lambdas as default values`() {
47         val source = """
48             // Signature format: 3.0
49             package androidx.collection {
50               public final class LruCacheKt {
51                 ctor public LruCacheKt();
52                 method public static <K, V> androidx.collection.LruCache<K,V> lruCache(int maxSize, kotlin.jvm.functions.Function2<? super K,? super V,java.lang.Integer> sizeOf = { _, _ -> 1 }, kotlin.jvm.functions.Function1<? super K,? extends V> create = { null as V? }, kotlin.jvm.functions.Function4<? super java.lang.Boolean,? super K,? super V,? super V,kotlin.Unit> onEntryRemoved = { _, _, _, _ -> });
53               }
54             }
55         """
56 
57         check(
58             format = FileFormat.V3,
59             inputKotlinStyleNulls = true,
60             signatureSource = source,
61             includeSignatureVersion = true,
62             api = source
63         )
64     }
65 
66     @Test
Invoking function with multiple parameters as parameter default valuenull67     fun `Invoking function with multiple parameters as parameter default value`() {
68         val source = """
69             // Signature format: 3.0
70             package abc {
71               public final class PopupKt {
72                 method public static void DropdownPopup(Type ident = SomeFunc(SomeVal, SomeVal));
73               }
74             }
75         """
76 
77         check(
78             format = FileFormat.V3,
79             inputKotlinStyleNulls = true,
80             signatureSource = source,
81             includeSignatureVersion = true,
82             api = source
83         )
84     }
85 
86     @Test
Handle enum constants as default valuesnull87     fun `Handle enum constants as default values`() {
88         val source = """
89             // Signature format: 3.0
90             package test.pkg {
91               public final class Foo {
92                 ctor public Foo();
93                 method public android.graphics.Bitmap? drawToBitmap(android.view.View, android.graphics.Bitmap.Config config = android.graphics.Bitmap.Config.ARGB_8888);
94                 method public void emptyLambda(kotlin.jvm.functions.Function0<kotlin.Unit> sizeOf = {});
95                 method public void method1(int p = 42, Integer? int2 = null, int p1 = 42, String str = "hello world", java.lang.String... args);
96                 method public void method2(int p, int int2 = (2 * int) * some.other.pkg.Constants.Misc.SIZE);
97                 method public void method3(String str, int p, int int2 = double(int) + str.length);
98                 field public static final test.pkg.Foo.Companion! Companion;
99               }
100               public static final class Foo.Companion {
101                 method public int double(int p);
102                 method public void print(test.pkg.Foo foo = test.pkg.Foo());
103               }
104               public final class LruCacheKt {
105                 ctor public LruCacheKt();
106                 method public static <K, V> android.util.LruCache<K,V> lruCache(int maxSize, kotlin.jvm.functions.Function2<? super K,? super V,java.lang.Integer> sizeOf = { _, _ -> 1 }, kotlin.jvm.functions.Function1<? super K,? extends V> create = { (V)null }, kotlin.jvm.functions.Function4<? super java.lang.Boolean,? super K,? super V,? super V,kotlin.Unit> onEntryRemoved = { _, _, _, _ ->  });
107               }
108             }
109             """
110 
111         check(
112             format = FileFormat.V3,
113             inputKotlinStyleNulls = true,
114             signatureSource = source,
115             includeSignatureVersion = true,
116             api = source
117         )
118     }
119 
120     @Test
Handle complex expressions as default valuesnull121     fun `Handle complex expressions as default values`() {
122         val source = """
123             // Signature format: 3.0
124             package androidx.paging {
125               public final class PagedListConfigKt {
126                 ctor public PagedListConfigKt();
127                 method public static androidx.paging.PagedList.Config Config(int pageSize, int prefetchDistance = pageSize, boolean enablePlaceholders = true, int initialLoadSizeHint = pageSize * PagedList.Config.Builder.DEFAULT_INITIAL_PAGE_MULTIPLIER, int maxSize = PagedList.Config.MAX_SIZE_UNBOUNDED);
128               }
129               public final class PagedListKt {
130                 ctor public PagedListKt();
131                 method public static <Key, Value> androidx.paging.PagedList<Value> PagedList(androidx.paging.DataSource<Key,Value> dataSource, androidx.paging.PagedList.Config config, java.util.concurrent.Executor notifyExecutor, java.util.concurrent.Executor fetchExecutor, androidx.paging.PagedList.BoundaryCallback<Value>? boundaryCallback = null, Key? initialKey = null);
132               }
133             }
134             package test.pkg {
135               public final class Foo {
136                 ctor public Foo();
137                 method public void method1(int p = 42, Integer? int2 = null, int p1 = 42, String str = "hello world", java.lang.String... args);
138                 method public void method2(int p, int int2 = (2 * int) * some.other.pkg.Constants.Misc.SIZE);
139                 method public void method3(str: String = "unbalanced), string", str2: String = ",");
140               }
141             }
142         """
143 
144         check(
145             format = FileFormat.V3,
146             inputKotlinStyleNulls = true,
147             signatureSource = source,
148             includeSignatureVersion = true,
149             api = source
150         )
151     }
152 
153     @Test
Annotation signatures requiring more complicated token matchingnull154     fun `Annotation signatures requiring more complicated token matching`() {
155         val source = """
156                 package test {
157                   public class MyTest {
158                     method @RequiresPermission(value="android.permission.AUTHENTICATE_ACCOUNTS", apis="..22") public boolean addAccountExplicitly(android.accounts.Account, String, android.os.Bundle);
159                     method @CheckResult(suggest="#enforceCallingOrSelfPermission(String,\"foo\",String)") public abstract int checkCallingOrSelfPermission(@NonNull String);
160                     method @RequiresPermission(anyOf={"android.permission.MANAGE_ACCOUNTS", "android.permission.USE_CREDENTIALS"}, apis="..22") public void invalidateAuthToken(String, String);
161                   }
162                 }
163                 """
164         check(
165             format = FileFormat.V2,
166             outputKotlinStyleNulls = false,
167             signatureSource = source,
168             api = source
169         )
170     }
171 
172     @Test
Multiple extendsnull173     fun `Multiple extends`() {
174         val source = """
175                 package test {
176                   public static interface PickConstructors extends test.pkg.PickConstructors.AutoCloseable {
177                   }
178                   public interface XmlResourceParser extends org.xmlpull.v1.XmlPullParser android.util.AttributeSet java.lang.AutoCloseable {
179                     method public void close();
180                   }
181                 }
182                 """
183         check(
184             outputKotlinStyleNulls = false,
185             signatureSource = source,
186             api = source
187         )
188     }
189 
190     @Test
Native and strictfp keywordsnull191     fun `Native and strictfp keywords`() {
192         check(
193             outputKotlinStyleNulls = false,
194             signatureSource = """
195                     package test.pkg {
196                       public class MyTest {
197                         method public native float dotWithNormal(float, float, float);
198                         method public static strictfp double toDegrees(double);
199                       }
200                     }
201                     """,
202             api = """
203                     package test.pkg {
204                       public class MyTest {
205                         method public float dotWithNormal(float, float, float);
206                         method public static double toDegrees(double);
207                       }
208                     }
209                     """
210         )
211     }
212 
213     @Test
Type use annotationsnull214     fun `Type use annotations`() {
215         check(
216             format = FileFormat.V2,
217             outputKotlinStyleNulls = false,
218             signatureSource = """
219                 package test.pkg {
220                   public class MyTest {
221                     method public static int codePointAt(char @NonNull [], int);
222                     method @NonNull public java.util.Set<java.util.Map.@NonNull Entry<K,V>> entrySet();
223                     method @NonNull public java.lang.annotation.@NonNull Annotation @NonNull [] getAnnotations();
224                     method @NonNull public abstract java.lang.annotation.@NonNull Annotation @NonNull [] @NonNull [] getParameterAnnotations();
225                     method @NonNull public @NonNull String @NonNull [] split(@NonNull String, int);
226                     method public static char @NonNull [] toChars(int);
227                   }
228                 }
229                 """,
230             api = """
231                 package test.pkg {
232                   public class MyTest {
233                     method public static int codePointAt(char @NonNull [], int);
234                     method @NonNull public java.util.Set<java.util.Map.@NonNull Entry<K,V>> entrySet();
235                     method @NonNull public java.lang.annotation.Annotation @NonNull [] getAnnotations();
236                     method @NonNull public abstract java.lang.annotation.Annotation @NonNull [] @NonNull [] getParameterAnnotations();
237                     method @NonNull public String @NonNull [] split(@NonNull String, int);
238                     method public static char @NonNull [] toChars(int);
239                   }
240                 }
241             """
242         )
243     }
244 
245     @Test
Vararg modifiernull246     fun `Vararg modifier`() {
247         val source = """
248                 package test.pkg {
249                   public final class Foo {
250                     ctor public Foo();
251                     method public void error(int p = "42", Integer int2 = "null", int p1 = "42", vararg String args);
252                   }
253                 }
254                 """
255         check(
256             outputKotlinStyleNulls = false,
257             signatureSource = source
258         )
259     }
260 
261     @Test
Infer fully qualified names from shorter namesnull262     fun `Infer fully qualified names from shorter names`() {
263         check(
264             format = FileFormat.V2,
265             signatureSource = """
266                 package test.pkg {
267                   public class MyTest {
268                     ctor public MyTest();
269                     method public int clamp(int);
270                     method public double convert(@Nullable Float, byte[], Iterable<java.io.File>);
271                   }
272                 }
273                 """,
274             api = """
275                 package test.pkg {
276                   public class MyTest {
277                     ctor public MyTest();
278                     method public int clamp(int);
279                     method public double convert(@Nullable Float, byte[], Iterable<java.io.File>);
280                   }
281                 }
282                 """
283         )
284     }
285 
286     @Test
Loading a signature file with alternate modifier ordernull287     fun `Loading a signature file with alternate modifier order`() {
288         // Regression test for https://github.com/android/android-ktx/issues/242
289         val source = """
290                 package test.pkg {
291                   deprecated public class MyTest {
292                     ctor deprecated public Foo(int, int);
293                     method deprecated public static final void edit(android.content.SharedPreferences, kotlin.jvm.functions.Function1<? super android.content.SharedPreferences.Editor,kotlin.Unit> action);
294                     field deprecated public static java.util.List<java.lang.String> LIST;
295                   }
296                 }
297                 """
298         check(
299             format = FileFormat.V2,
300             signatureSource = source,
301             api = """
302                 package test.pkg {
303                   @Deprecated public class MyTest {
304                     ctor @Deprecated public MyTest(int, int);
305                     method @Deprecated public static final void edit(android.content.SharedPreferences, kotlin.jvm.functions.Function1<? super android.content.SharedPreferences.Editor,kotlin.Unit> action);
306                     field @Deprecated public static java.util.List<java.lang.String> LIST;
307                   }
308                 }
309                 """
310         )
311     }
312 
313     @Test
Test generics, superclasses and interfacesnull314     fun `Test generics, superclasses and interfaces`() {
315         val source = """
316             package a.b.c {
317               public interface MyStream<T, S extends a.b.c.MyStream<T, S>> {
318               }
319             }
320             package test.pkg {
321               public enum Foo {
322                 ctor public Foo(int);
323                 ctor public Foo(int, int);
324                 method public static test.pkg.Foo valueOf(String);
325                 method public static final test.pkg.Foo[] values();
326                 enum_constant public static final test.pkg.Foo A;
327                 enum_constant public static final test.pkg.Foo B;
328               }
329               public interface MyBaseInterface {
330               }
331               public interface MyInterface<T> extends test.pkg.MyBaseInterface {
332               }
333               public interface MyInterface2<T extends java.lang.Number> extends test.pkg.MyBaseInterface {
334               }
335               public abstract static class MyInterface2.Range<T extends java.lang.Comparable<? super T>> {
336                 ctor public MyInterface2.Range();
337               }
338               public static class MyInterface2.TtsSpan<C extends test.pkg.MyInterface<?>> {
339                 ctor public MyInterface2.TtsSpan();
340               }
341               public final class Test<T> {
342                 ctor public Test();
343                 method public abstract <T extends java.util.Collection<java.lang.String>> T addAllTo(T);
344                 method public static <T & java.lang.Comparable<? super T>> T max(java.util.Collection<? extends T>);
345                 method public <X extends java.lang.Throwable> T orElseThrow(java.util.function.Supplier<? extends X>) throws java.lang.Throwable;
346                 field public static java.util.List<java.lang.String> LIST;
347               }
348             }
349             """
350 
351         check(
352             format = FileFormat.V2,
353             signatureSource = source,
354             api = source
355         )
356     }
357 
358     @Test
Test constantsnull359     fun `Test constants`() {
360         val source = """
361                 package test.pkg {
362                   public class Foo2 {
363                     ctor public Foo2();
364                     field public static final String GOOD_IRI_CHAR = "a-zA-Z0-9\u00a0-\ud7ff\uf900-\ufdcf\ufdf0-\uffef";
365                     field public static final char HEX_INPUT = 61184; // 0xef00 '\uef00'
366                     field protected int field00;
367                     field public static final boolean field01 = true;
368                     field public static final int field02 = 42; // 0x2a
369                     field public static final long field03 = 42L; // 0x2aL
370                     field public static final short field04 = 5; // 0x5
371                     field public static final byte field05 = 5; // 0x5
372                     field public static final char field06 = 99; // 0x0063 'c'
373                     field public static final float field07 = 98.5f;
374                     field public static final double field08 = 98.5;
375                     field public static final String field09 = "String with \"escapes\" and \u00a9...";
376                     field public static final double field10 = (0.0/0.0);
377                     field public static final double field11 = (1.0/0.0);
378                   }
379                 }
380                 """
381 
382         check(
383             signatureSource = source,
384             api = source
385         )
386     }
387 
388     @Test
Test inner classesnull389     fun `Test inner classes`() {
390         val source = """
391                 package test.pkg {
392                   public abstract class Foo {
393                     ctor public Foo();
394                     method @Deprecated public static final void method1();
395                     method @Deprecated public static final void method2();
396                   }
397                   @Deprecated protected static final class Foo.Inner1 {
398                     ctor protected Foo.Inner1();
399                   }
400                   @Deprecated protected abstract static class Foo.Inner2 {
401                     ctor protected Foo.Inner2();
402                   }
403                   @Deprecated protected static interface Foo.Inner3 {
404                     method public default void method3();
405                     method public abstract static void method4(int);
406                   }
407                 }
408                 """
409 
410         check(
411             signatureSource = source,
412             api = source
413         )
414     }
415 
416     @Test
Test throwsnull417     fun `Test throws`() {
418         val source = """
419                 package test.pkg {
420                   public final class Test<T> {
421                     ctor public Test();
422                     method public <X extends java.lang.Throwable> T orElseThrow(java.util.function.Supplier<? extends X>) throws java.lang.Throwable;
423                   }
424                 }
425                 """
426 
427         check(
428             format = FileFormat.V2,
429             signatureSource = source,
430             api = source
431         )
432     }
433 
434     @Test
Loading a signature file with annotations on classes, fields, methods and parametersnull435     fun `Loading a signature file with annotations on classes, fields, methods and parameters`() {
436         @Language("TEXT")
437         val source = """
438                 // Signature format: 3.0
439                 package test.pkg {
440                   @UiThread public class MyTest {
441                     ctor public MyTest();
442                     method @IntRange(from=10, to=20) public int clamp(int);
443                     method public Double? convert(Float myPublicName);
444                     field public Number? myNumber;
445                   }
446                 }
447                 """
448 
449         check(
450             format = FileFormat.V3,
451             signatureSource = source,
452             api = source
453         )
454     }
455 
456     @Test
Enumsnull457     fun `Enums`() {
458         val source = """
459                 package test.pkg {
460                   public enum Foo {
461                     enum_constant public static final test.pkg.Foo A;
462                     enum_constant public static final test.pkg.Foo B;
463                   }
464                 }
465                 """
466 
467         check(
468             outputKotlinStyleNulls = false,
469             signatureSource = source,
470             api = source
471         )
472     }
473 
474     @Test
Annotationsnull475     fun `Annotations`() {
476         val source = """
477                 package android.annotation {
478                   public @interface SuppressLint {
479                     method public abstract String[] value();
480                   }
481                 }
482                 """
483 
484         check(
485             outputKotlinStyleNulls = false,
486             signatureSource = source,
487             api = source
488         )
489     }
490 
491     @Test
Annotations on packagesnull492     fun `Annotations on packages`() {
493         val source = """
494                 package @RestrictTo(androidx.annotation.RestrictTo.Scope.SUBCLASSES) @RestrictTo(androidx.annotation.RestrictTo.Scope.SUBCLASSES) test.pkg {
495                   public abstract class Class1 {
496                     ctor public Class1();
497                   }
498                 }
499                 """
500 
501         check(
502             outputKotlinStyleNulls = false,
503             signatureSource = source,
504             api = source
505         )
506     }
507 
508     @Test
Sort throws list by full namenull509     fun `Sort throws list by full name`() {
510         check(
511             format = FileFormat.V2,
512             signatureSource = """
513                     package android.accounts {
514                       public abstract interface AccountManagerFuture<V> {
515                         method public abstract boolean cancel(boolean);
516                         method public abstract V getResult() throws android.accounts.OperationCanceledException, java.io.IOException, android.accounts.AuthenticatorException;
517                         method public abstract V getResult(long, java.util.concurrent.TimeUnit) throws android.accounts.OperationCanceledException, java.io.IOException, android.accounts.AuthenticatorException;
518                         method public abstract boolean isCancelled();
519                         method public abstract boolean isDone();
520                       }
521                       public class AuthenticatorException extends java.lang.Throwable {
522                       }
523                       public class OperationCanceledException extends java.lang.Throwable {
524                       }
525                     }
526                     """,
527             api = """
528                     package android.accounts {
529                       public interface AccountManagerFuture<V> {
530                         method public boolean cancel(boolean);
531                         method public V getResult() throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException;
532                         method public V getResult(long, java.util.concurrent.TimeUnit) throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException;
533                         method public boolean isCancelled();
534                         method public boolean isDone();
535                       }
536                       public class AuthenticatorException extends java.lang.Throwable {
537                       }
538                       public class OperationCanceledException extends java.lang.Throwable {
539                       }
540                     }
541                     """
542         )
543     }
544 
545     @Test
Loading a signature file with default valuesnull546     fun `Loading a signature file with default values`() {
547         @Language("TEXT")
548         val source = """
549                 // Signature format: 3.0
550                 package test.pkg {
551                   public final class Foo {
552                     ctor public Foo();
553                     method public final void error(int p = 42, Integer? int2 = null);
554                   }
555                   public class Foo2 {
556                     ctor public Foo2();
557                     method public void foo(String! = null, String! = "(Hello) World", int = 42);
558                   }
559                 }
560                 """
561 
562         check(
563             format = FileFormat.V3,
564             signatureSource = source,
565             api = source
566         )
567     }
568 
569     @Test
Signatures with default annotation method valuesnull570     fun `Signatures with default annotation method values`() {
571         val source = """
572                 // Signature format: 3.0
573                 package libcore.util {
574                   public @interface NonNull {
575                     method public abstract int from() default java.lang.Integer.MIN_VALUE;
576                     method public abstract double fromWithCast() default (double)java.lang.Float.NEGATIVE_INFINITY;
577                     method public abstract String myString() default "This is a \"string\"";
578                     method public abstract int to() default java.lang.Integer.MAX_VALUE;
579                   }
580                 }
581                 """
582 
583         check(
584             format = FileFormat.V3,
585             signatureSource = source,
586             api = source
587         )
588     }
589 
590     @Test
Signatures with many annotationsnull591     fun `Signatures with many annotations`() {
592         val source = """
593             // Signature format: 2.0
594             package libcore.util {
595               @java.lang.annotation.Documented @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public @interface NonNull {
596                 method public abstract int from() default java.lang.Integer.MIN_VALUE;
597                 method public abstract int to() default java.lang.Integer.MAX_VALUE;
598               }
599             }
600             package test.pkg {
601               public class Test {
602                 ctor public Test();
603                 method @NonNull public Object compute();
604               }
605             }
606         """
607 
608         check(
609             format = FileFormat.V2,
610             signatureSource = source,
611             api = source
612         )
613     }
614 
615     @Test
Kotlin Propertiesnull616     fun `Kotlin Properties`() {
617         val source = """
618                 // Signature format: 2.0
619                 package test.pkg {
620                   public final class Kotlin {
621                     ctor public Kotlin(String property1, int arg2);
622                     method public String getProperty1();
623                     method public String getProperty2();
624                     method public void setProperty2(String p);
625                     property public final String property2;
626                   }
627                 }
628                 """
629 
630         check(
631             format = FileFormat.V2,
632             signatureSource = source,
633             api = source
634         )
635     }
636 
637     @Test
Deprecated enum constantnull638     fun `Deprecated enum constant`() {
639         val source = """
640                 // Signature format: 3.0
641                 package androidx.annotation {
642                   @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.ANNOTATION_TYPE, java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.PACKAGE}) public @interface RestrictTo {
643                     method public abstract androidx.annotation.RestrictTo.Scope[] value();
644                   }
645                   public enum RestrictTo.Scope {
646                     enum_constant @Deprecated public static final androidx.annotation.RestrictTo.Scope GROUP_ID;
647                     enum_constant public static final androidx.annotation.RestrictTo.Scope LIBRARY;
648                     enum_constant public static final androidx.annotation.RestrictTo.Scope LIBRARY_GROUP;
649                     enum_constant public static final androidx.annotation.RestrictTo.Scope SUBCLASSES;
650                     enum_constant public static final androidx.annotation.RestrictTo.Scope TESTS;
651                   }
652                 }
653                 """
654 
655         check(
656             format = FileFormat.V3,
657             inputKotlinStyleNulls = true,
658             outputKotlinStyleNulls = true,
659             signatureSource = source,
660             api = source
661         )
662     }
663 
664     @Test
Type parameters in v3 formatnull665     fun `Type parameters in v3 format`() {
666         val source = """
667                 // Signature format: 3.0
668                 package androidx.collection {
669                   public class Constants {
670                     field public static final String GOOD_IRI_CHAR = "a-zA-Z0-9\u00a0-\ud7ff\uf900-\ufdcf\ufdf0-\uffef";
671                     field public static final char HEX_INPUT = 61184; // 0xef00 '\uef00'
672                     field protected int field00;
673                     field public static final boolean field01 = true;
674                     field public static final int field02 = 42; // 0x2a
675                     field public static final String field09 = "String with \"escapes\" and \u00a9...";
676                   }
677                   public class MyMap<Key, Value> {
678                     method public Key! getReplacement(Key!);
679                   }
680                 }
681                 package androidx.paging {
682                   public abstract class DataSource<Key, Value> {
683                     method @AnyThread public void addInvalidatedCallback(androidx.paging.DataSource.InvalidatedCallback);
684                     method @AnyThread public void invalidate();
685                     method @WorkerThread public boolean isInvalid();
686                     method public abstract <ToValue> androidx.paging.DataSource<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue>);
687                     method public abstract <ToValue> androidx.paging.DataSource<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>>);
688                     method @AnyThread public void removeInvalidatedCallback(androidx.paging.DataSource.InvalidatedCallback);
689                   }
690                   public abstract class ItemKeyedDataSource<Key, Value> extends androidx.paging.DataSource<Key, Value> {
691                     method public abstract Key getKey(Value);
692                     method public boolean isContiguous();
693                     method public abstract void loadAfter(androidx.paging.ItemKeyedDataSource.LoadParams<Key>, androidx.paging.ItemKeyedDataSource.LoadCallback<Value>);
694                     method public abstract void loadBefore(androidx.paging.ItemKeyedDataSource.LoadParams<Key>, androidx.paging.ItemKeyedDataSource.LoadCallback<Value>);
695                     method public abstract void loadInitial(androidx.paging.ItemKeyedDataSource.LoadInitialParams<Key>, androidx.paging.ItemKeyedDataSource.LoadInitialCallback<Value>);
696                     method public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> map(androidx.arch.core.util.Function<Value,ToValue>);
697                     method public final <ToValue> androidx.paging.ItemKeyedDataSource<Key,ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>,java.util.List<ToValue>>);
698                   }
699                 }
700                 """
701         check(
702             format = FileFormat.V3,
703             inputKotlinStyleNulls = true,
704             outputKotlinStyleNulls = true,
705             signatureSource = source,
706             api = source
707         )
708     }
709 
710     @Test
Signatures with reified in type parametersnull711     fun `Signatures with reified in type parameters`() {
712         val source = """
713                 package test.pkg {
714                   public final class TestKt {
715                     ctor public TestKt();
716                     method public static inline <T> void a(T);
717                     method public static inline <reified T> void b(T);
718                     method public static inline <reified T> void e(T);
719                     method public static inline <reified T> void f(T, T);
720                   }
721                 }
722                 """
723 
724         check(
725             format = FileFormat.V2,
726             signatureSource = source,
727             api = source
728         )
729     }
730 
731     @Test
Suspended methodsnull732     fun `Suspended methods`() {
733         val source = """
734                 package test.pkg {
735                   public final class TestKt {
736                     ctor public TestKt();
737                     method public static suspend inline Object hello(kotlin.coroutines.experimental.Continuation<? super kotlin.Unit>);
738                   }
739                 }
740                 """
741 
742         check(
743             format = FileFormat.V2,
744             signatureSource = source,
745             api = source
746         )
747     }
748 
749     @Test
Complicated annotationsnull750     fun `Complicated annotations`() {
751         val source = """
752                 package android.app {
753                   public static class ActionBar {
754                     field @android.view.ViewDebug.ExportedProperty(category="layout", mapping={@android.view.ViewDebug.IntToString(from=0xffffffff, to="NONE"), @android.view.ViewDebug.IntToString(from=android.view.Gravity.NO_GRAVITY, to="NONE"), @android.view.ViewDebug.IntToString(from=android.view.Gravity.TOP, to="TOP"), @android.view.ViewDebug.IntToString(from=android.view.Gravity.BOTTOM, to="BOTTOM"), @android.view.ViewDebug.IntToString(from=android.view.Gravity.LEFT, to="LEFT"), @android.view.ViewDebug.IntToString(from=android.view.Gravity.RIGHT, to="RIGHT"), @android.view.ViewDebug.IntToString(from=android.view.Gravity.START, to="START"), @android.view.ViewDebug.IntToString(from=android.view.Gravity.END, to="END"), @android.view.ViewDebug.IntToString(from=android.view.Gravity.CENTER_VERTICAL, to="CENTER_VERTICAL"), @android.view.ViewDebug.IntToString(from=android.view.Gravity.FILL_VERTICAL, to="FILL_VERTICAL"), @android.view.ViewDebug.IntToString(from=android.view.Gravity.CENTER_HORIZONTAL, to="CENTER_HORIZONTAL"), @android.view.ViewDebug.IntToString(from=android.view.Gravity.FILL_HORIZONTAL, to="FILL_HORIZONTAL"), @android.view.ViewDebug.IntToString(from=android.view.Gravity.CENTER, to="CENTER"), @android.view.ViewDebug.IntToString(from=android.view.Gravity.FILL, to="FILL")}) public int gravity;
755                   }
756                 }
757                 """
758 
759         val expectedApi = """
760                 package android.app {
761                   public static class ActionBar {
762                     field public int gravity;
763                   }
764                 }
765                 """
766 
767         check(
768             signatureSource = source,
769             api = expectedApi
770         )
771     }
772 }
773