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