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