1 /* 2 * Copyright (C) 2020 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.cli.common.ARG_ERROR 20 import com.android.tools.metalava.lint.DefaultLintErrorMessage 21 import com.android.tools.metalava.model.provider.Capability 22 import com.android.tools.metalava.model.testing.RequiresCapabilities 23 import com.android.tools.metalava.model.text.FileFormat 24 import com.android.tools.metalava.testing.java 25 import com.android.tools.metalava.testing.kotlin 26 import org.junit.Test 27 28 class ApiAnalyzerTest : DriverTest() { 29 @Test Hidden abstract method with show @SystemApinull30 fun `Hidden abstract method with show @SystemApi`() { 31 check( 32 showAnnotations = arrayOf("android.annotation.SystemApi"), 33 expectedIssues = 34 """ 35 src/test/pkg/PublicClass.java:5: error: badAbstractHiddenMethod cannot be hidden and abstract when PublicClass has a visible constructor, in case a third-party attempts to subclass it. [HiddenAbstractMethod] 36 src/test/pkg/PublicClass.java:6: error: badPackagePrivateMethod cannot be hidden and abstract when PublicClass has a visible constructor, in case a third-party attempts to subclass it. [HiddenAbstractMethod] 37 src/test/pkg/SystemApiClass.java:7: error: badAbstractHiddenMethod cannot be hidden and abstract when SystemApiClass has a visible constructor, in case a third-party attempts to subclass it. [HiddenAbstractMethod] 38 """, 39 expectedFail = DefaultLintErrorMessage, 40 sourceFiles = 41 arrayOf( 42 java( 43 """ 44 package test.pkg; 45 import android.annotation.SystemApi; 46 public abstract class PublicClass { 47 /** @hide */ 48 public abstract boolean badAbstractHiddenMethod() { return true; } 49 abstract void badPackagePrivateMethod() { } 50 /** 51 * This method does not fail because it is visible due to showAnnotations, 52 * instead it will fail when running analysis on public API. See test below. 53 * @hide 54 */ 55 @SystemApi 56 public abstract boolean goodAbstractSystemHiddenMethod() { return true; } 57 } 58 """ 59 ), 60 java( 61 """ 62 package test.pkg; 63 import android.annotation.SystemApi; 64 public abstract class PublicClassWithHiddenConstructor { 65 private PublicClassWithHiddenConstructor() { } 66 /** @hide */ 67 public abstract boolean goodAbstractHiddenMethod() { return true; } 68 } 69 """ 70 ), 71 java( 72 """ 73 package test.pkg; 74 import android.annotation.SystemApi; 75 /** @hide */ 76 @SystemApi 77 public abstract class SystemApiClass { 78 /** @hide */ 79 public abstract boolean badAbstractHiddenMethod() { return true; } 80 /** 81 * This method is OK, because it matches visibility of the class 82 * @hide 83 */ 84 @SystemApi 85 public abstract boolean goodAbstractSystemHiddenMethod() { return true; } 86 public abstract boolean goodAbstractPublicMethod() { return true; } 87 } 88 """ 89 ), 90 java( 91 """ 92 package test.pkg; 93 import android.annotation.SystemApi; 94 /** This class is OK because it is all hidden @hide */ 95 public abstract class HiddenClass { 96 public abstract boolean goodAbstractHiddenMethod() { return true; } 97 } 98 """ 99 ), 100 systemApiSource 101 ) 102 ) 103 } 104 105 @Test Hidden abstract method for public APInull106 fun `Hidden abstract method for public API`() { 107 check( 108 expectedIssues = 109 """ 110 src/test/pkg/PublicClass.java:5: error: badAbstractHiddenMethod cannot be hidden and abstract when PublicClass has a visible constructor, in case a third-party attempts to subclass it. [HiddenAbstractMethod] 111 src/test/pkg/PublicClass.java:6: error: badPackagePrivateMethod cannot be hidden and abstract when PublicClass has a visible constructor, in case a third-party attempts to subclass it. [HiddenAbstractMethod] 112 src/test/pkg/PublicClass.java:9: error: badAbstractSystemHiddenMethod cannot be hidden and abstract when PublicClass has a visible constructor, in case a third-party attempts to subclass it. [HiddenAbstractMethod] 113 """, 114 expectedFail = DefaultLintErrorMessage, 115 sourceFiles = 116 arrayOf( 117 java( 118 """ 119 package test.pkg; 120 import android.annotation.SystemApi; 121 public abstract class PublicClass { 122 /** @hide */ 123 public abstract boolean badAbstractHiddenMethod() { return true; } 124 abstract void badPackagePrivateMethod() { } 125 /** @hide */ 126 @SystemApi 127 public abstract boolean badAbstractSystemHiddenMethod() { return true; } 128 } 129 """ 130 ), 131 systemApiSource 132 ) 133 ) 134 } 135 136 @Test Deprecation mismatch check look at inherited docs for overriding methodsnull137 fun `Deprecation mismatch check look at inherited docs for overriding methods`() { 138 check( 139 expectedIssues = 140 """ 141 src/test/pkg/MyClass.java:20: error: Method test.pkg.MyClass.inheritedNoCommentInParent(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match [DeprecationMismatch] 142 src/test/pkg/MyClass.java:23: error: Method test.pkg.MyClass.notInheritedNoComment(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match [DeprecationMismatch] 143 src/test/pkg/MyInterface.java:17: error: Method test.pkg.MyInterface.inheritedNoCommentInParent(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match [DeprecationMismatch] 144 """, 145 expectedFail = DefaultLintErrorMessage, 146 sourceFiles = 147 arrayOf( 148 java( 149 """ 150 package test.pkg; 151 152 public interface MyInterface { 153 /** @deprecated Use XYZ instead. */ 154 @Deprecated 155 void inheritedNoComment(); 156 157 /** @deprecated Use XYZ instead. */ 158 @Deprecated 159 void inheritedWithComment(); 160 161 /** @deprecated Use XYZ instead. */ 162 @Deprecated 163 void inheritedWithInheritDoc(); 164 165 @Deprecated 166 void inheritedNoCommentInParent(); 167 } 168 """, 169 ), 170 java( 171 """ 172 package test.pkg; 173 174 public class MyClass implements MyInterface { 175 @Deprecated 176 @Override 177 public void inheritedNoComment() {} 178 179 /** @deprecated Use XYZ instead. */ 180 @Deprecated 181 @Override 182 public void inheritedWithComment() {} 183 184 /** {@inheritDoc} */ 185 @Deprecated 186 @Override 187 public void inheritedWithInheritDoc() {} 188 189 @Deprecated 190 @Override 191 public void inheritedNoCommentInParent() {} 192 193 @Deprecated 194 public void notInheritedNoComment() {} 195 } 196 """ 197 ) 198 ) 199 ) 200 } 201 202 @Test Test that usage of a hidden class as type parameter of an outer class is flaggednull203 fun `Test that usage of a hidden class as type parameter of an outer class is flagged`() { 204 check( 205 expectedIssues = 206 """ 207 src/test/pkg/Foo.java:3: warning: Field Foo.fieldReferencesHidden1 references hidden type test.pkg.Hidden. [HiddenTypeParameter] 208 src/test/pkg/Foo.java:3: error: Class test.pkg.Hidden is hidden but was referenced (in field type) from public field test.pkg.Foo.fieldReferencesHidden1 [ReferencesHidden] 209 src/test/pkg/Foo.java:4: warning: Field Foo.fieldReferencesHidden2 references hidden type test.pkg.Hidden. [HiddenTypeParameter] 210 src/test/pkg/Foo.java:4: error: Class test.pkg.Hidden is hidden but was referenced (in field type) from public field test.pkg.Foo.fieldReferencesHidden2 [ReferencesHidden] 211 src/test/pkg/Foo.java:5: warning: Field Foo.fieldReferencesHidden3 references hidden type test.pkg.Hidden. [HiddenTypeParameter] 212 src/test/pkg/Foo.java:5: error: Class test.pkg.Hidden is hidden but was referenced (in field type) from public field test.pkg.Foo.fieldReferencesHidden3 [ReferencesHidden] 213 src/test/pkg/Foo.java:6: warning: Field Foo.fieldReferencesHidden4 references hidden type test.pkg.Hidden. [HiddenTypeParameter] 214 src/test/pkg/Foo.java:6: error: Class test.pkg.Hidden is hidden but was referenced (in field type) from public field test.pkg.Foo.fieldReferencesHidden4 [ReferencesHidden] 215 """, 216 expectedFail = DefaultLintErrorMessage, 217 sourceFiles = 218 arrayOf( 219 java( 220 """ 221 package test.pkg; 222 /** @hide */ 223 public class Hidden {} 224 """ 225 ), 226 java( 227 """ 228 package test.pkg; 229 public class Outer<P1> { 230 public class Inner<P2> {} 231 } 232 """ 233 ), 234 java( 235 """ 236 package test.pkg; 237 public class Foo { 238 public Hidden fieldReferencesHidden1; 239 public Outer<Hidden> fieldReferencesHidden2; 240 public Outer<Foo>.Inner<Hidden> fieldReferencesHidden3; 241 public Outer<Hidden>.Inner<Foo> fieldReferencesHidden4; 242 } 243 """ 244 ) 245 ) 246 ) 247 } 248 249 @Test Test inheriting methods from hidden class preserves deprecated statusnull250 fun `Test inheriting methods from hidden class preserves deprecated status`() { 251 check( 252 sourceFiles = 253 arrayOf( 254 java( 255 """ 256 package test.pkg; 257 258 class Hidden { 259 /** @deprecated */ 260 public <T> void foo(@Deprecated T t) {} 261 262 /** @deprecated */ 263 public void bar() {} 264 265 public void baz(@Deprecated int i) {} 266 } 267 """ 268 ), 269 java( 270 """ 271 package test.pkg; 272 273 public class Concrete extends Hidden<String> { 274 } 275 """ 276 ), 277 ), 278 format = FileFormat.V2, 279 api = 280 """ 281 // Signature format: 2.0 282 package test.pkg { 283 public class Concrete { 284 ctor public Concrete(); 285 method @Deprecated public void bar(); 286 method public void baz(@Deprecated int); 287 method @Deprecated public <T> void foo(@Deprecated T); 288 } 289 } 290 """, 291 stubFiles = 292 arrayOf( 293 java( 294 """ 295 package test.pkg; 296 @SuppressWarnings({"unchecked", "deprecation", "all"}) 297 public class Concrete { 298 public Concrete() { throw new RuntimeException("Stub!"); } 299 /** @deprecated */ 300 @Deprecated 301 public void bar() { throw new RuntimeException("Stub!"); } 302 public void baz(@Deprecated int i) { throw new RuntimeException("Stub!"); } 303 /** @deprecated */ 304 @Deprecated 305 public <T> void foo(@Deprecated T t) { throw new RuntimeException("Stub!"); } 306 } 307 """ 308 ), 309 ), 310 ) 311 } 312 313 @Test Test inheriting methods from hidden generic class preserves deprecated statusnull314 fun `Test inheriting methods from hidden generic class preserves deprecated status`() { 315 check( 316 sourceFiles = 317 arrayOf( 318 java( 319 """ 320 package test.pkg; 321 322 class Hidden<T> { 323 /** @deprecated */ 324 public void foo(@Deprecated T t) {} 325 326 /** @deprecated */ 327 public void bar() {} 328 329 public void baz(@Deprecated int i) {} 330 } 331 332 """ 333 ), 334 java( 335 """ 336 package test.pkg; 337 338 public class Concrete extends Hidden<String> { 339 } 340 """ 341 ), 342 ), 343 format = FileFormat.V2, 344 api = 345 """ 346 // Signature format: 2.0 347 package test.pkg { 348 public class Concrete { 349 ctor public Concrete(); 350 method @Deprecated public void bar(); 351 method public void baz(@Deprecated int); 352 method @Deprecated public void foo(@Deprecated String); 353 } 354 } 355 """, 356 stubFiles = 357 arrayOf( 358 java( 359 """ 360 package test.pkg; 361 @SuppressWarnings({"unchecked", "deprecation", "all"}) 362 public class Concrete { 363 public Concrete() { throw new RuntimeException("Stub!"); } 364 /** @deprecated */ 365 @Deprecated 366 public void bar() { throw new RuntimeException("Stub!"); } 367 public void baz(@Deprecated int i) { throw new RuntimeException("Stub!"); } 368 /** @deprecated */ 369 @Deprecated 370 public void foo(@Deprecated java.lang.String t) { throw new RuntimeException("Stub!"); } 371 } 372 """ 373 ), 374 ), 375 ) 376 } 377 378 @RequiresCapabilities(Capability.KOTLIN) 379 @Test Test deprecated class and parameters are output in kotlinnull380 fun `Test deprecated class and parameters are output in kotlin`() { 381 check( 382 sourceFiles = 383 arrayOf( 384 kotlin( 385 """ 386 package test.pkg 387 388 @Deprecated 389 class Foo( 390 @Deprecated var i: Int, 391 @Deprecated var b: Boolean, 392 ) 393 """ 394 ), 395 ), 396 format = FileFormat.V2, 397 api = 398 """ 399 // Signature format: 2.0 400 package test.pkg { 401 @Deprecated public final class Foo { 402 ctor @Deprecated public Foo(@Deprecated int i, @Deprecated boolean b); 403 method @Deprecated public boolean getB(); 404 method @Deprecated public int getI(); 405 method @Deprecated public void setB(boolean); 406 method @Deprecated public void setI(int); 407 property @Deprecated public final boolean b; 408 property @Deprecated public final int i; 409 } 410 } 411 """, 412 ) 413 } 414 415 @RequiresCapabilities(Capability.KOTLIN) 416 @Test Deprecation when ignoring commentsnull417 fun `Deprecation when ignoring comments`() { 418 check( 419 extraArguments = arrayOf(ARG_SKIP_READING_COMMENTS, ARG_ERROR, "ReferencesDeprecated"), 420 sourceFiles = 421 arrayOf( 422 kotlin( 423 """ 424 package test.pkg 425 426 @Deprecated 427 class TestClass( 428 val content: String, 429 ) 430 431 @Deprecated 432 val TestClass.propertyDeprecated: String 433 get() = TestClass.content 434 435 @get:Deprecated 436 val TestClass.getterDeprecated: String 437 get() = TestClass.content 438 439 /** 440 * @deprecated 441 */ 442 val TestClass.commentDeprecated: String 443 get() = TestClass.content 444 445 """ 446 ), 447 ), 448 format = FileFormat.V2, 449 expectedFail = DefaultLintErrorMessage, 450 expectedIssues = 451 """ 452 src/test/pkg/TestClass.kt:20: error: Parameter references deprecated type test.pkg.TestClass in test.pkg.TestClassKt.getCommentDeprecated(): this method should also be deprecated [ReferencesDeprecated] 453 """, 454 ) 455 } 456 457 @Test Test inherited method from hidden class into deprecated class inherits deprecated statusnull458 fun `Test inherited method from hidden class into deprecated class inherits deprecated status`() { 459 check( 460 sourceFiles = 461 arrayOf( 462 java( 463 """ 464 package test.pkg; 465 466 class Hidden { 467 public void bar() {} 468 } 469 """ 470 ), 471 java( 472 """ 473 package test.pkg; 474 475 /** @deprecated */ 476 public class Concrete extends Hidden<String> { 477 } 478 """ 479 ), 480 ), 481 format = FileFormat.V2, 482 api = 483 """ 484 // Signature format: 2.0 485 package test.pkg { 486 @Deprecated public class Concrete { 487 ctor @Deprecated public Concrete(); 488 method @Deprecated public void bar(); 489 } 490 } 491 """, 492 stubFiles = 493 arrayOf( 494 java( 495 """ 496 package test.pkg; 497 /** @deprecated */ 498 @SuppressWarnings({"unchecked", "deprecation", "all"}) 499 @Deprecated 500 public class Concrete { 501 @Deprecated 502 public Concrete() { throw new RuntimeException("Stub!"); } 503 @Deprecated 504 public void bar() { throw new RuntimeException("Stub!"); } 505 } 506 """ 507 ), 508 ), 509 ) 510 } 511 512 @RequiresCapabilities(Capability.KOTLIN) 513 @Test Test warnings for usage of hidden interface typenull514 fun `Test warnings for usage of hidden interface type`() { 515 check( 516 sourceFiles = 517 arrayOf( 518 kotlin( 519 """ 520 package test.pkg 521 /** @suppress */ 522 interface HiddenInterface 523 class PublicClass { 524 fun returnsHiddenInterface(): HiddenInterface = TODO() 525 } 526 """ 527 ) 528 ), 529 api = 530 """ 531 // Signature format: 5.0 532 package test.pkg { 533 public final class PublicClass { 534 ctor public PublicClass(); 535 method public test.pkg.HiddenInterface returnsHiddenInterface(); 536 } 537 } 538 """, 539 expectedFail = DefaultLintErrorMessage, 540 expectedIssues = 541 """ 542 src/test/pkg/HiddenInterface.kt:5: warning: Method test.pkg.PublicClass.returnsHiddenInterface() references hidden type test.pkg.HiddenInterface. [HiddenTypeParameter] 543 src/test/pkg/HiddenInterface.kt:5: warning: Return type of unavailable type test.pkg.HiddenInterface in test.pkg.PublicClass.returnsHiddenInterface() [UnavailableSymbol] 544 src/test/pkg/HiddenInterface.kt:5: error: Class test.pkg.HiddenInterface is hidden but was referenced (in return type) from public method test.pkg.PublicClass.returnsHiddenInterface() [ReferencesHidden] 545 """, 546 ) 547 } 548 549 @Test Test PrivateSuperclass for inner classnull550 fun `Test PrivateSuperclass for inner class`() { 551 check( 552 sourceFiles = 553 arrayOf( 554 java( 555 """ 556 package test.pkg; 557 public class Container { 558 private class PrivateInnerClass {} 559 public class PublicInnerClass extends PrivateInnerClass {} 560 } 561 """ 562 ) 563 ), 564 api = 565 """ 566 package test.pkg { 567 public class Container { 568 ctor public Container(); 569 } 570 public class Container.PublicInnerClass { 571 ctor public Container.PublicInnerClass(); 572 } 573 } 574 """, 575 expectedIssues = 576 "src/test/pkg/Container.java:4: warning: Public class test.pkg.Container.PublicInnerClass extends private class test.pkg.Container.PrivateInnerClass [PrivateSuperclass]" 577 ) 578 } 579 580 @Test Test references deprecated errors do not apply to inner class of deprecated classnull581 fun `Test references deprecated errors do not apply to inner class of deprecated class`() { 582 check( 583 sourceFiles = 584 arrayOf( 585 java( 586 """ 587 package test.pkg; 588 /** @deprecated */ 589 @Deprecated 590 public class DeprecatedOuterClass { 591 public class EffectivelyDeprecatedInnerClass extends DeprecatedOuterClass { 592 public void usesDeprecatedOuterClass(DeprecatedOuterClass doc) {} 593 } 594 } 595 """ 596 ), 597 java( 598 """ 599 package test.pkg; 600 public class NotDeprecatedClass extends DeprecatedOuterClass { 601 public void usesDeprecatedOuterClass(DeprecatedOuterClass doc) {} 602 } 603 """ 604 ) 605 ), 606 api = 607 """ 608 package test.pkg { 609 @Deprecated public class DeprecatedOuterClass { 610 ctor @Deprecated public DeprecatedOuterClass(); 611 } 612 @Deprecated public class DeprecatedOuterClass.EffectivelyDeprecatedInnerClass extends test.pkg.DeprecatedOuterClass { 613 ctor @Deprecated public DeprecatedOuterClass.EffectivelyDeprecatedInnerClass(); 614 method @Deprecated public void usesDeprecatedOuterClass(test.pkg.DeprecatedOuterClass!); 615 } 616 public class NotDeprecatedClass extends test.pkg.DeprecatedOuterClass { 617 ctor public NotDeprecatedClass(); 618 method public void usesDeprecatedOuterClass(test.pkg.DeprecatedOuterClass!); 619 } 620 } 621 """, 622 extraArguments = 623 arrayOf(ARG_ERROR, "ReferencesDeprecated", ARG_ERROR, "ExtendsDeprecated"), 624 expectedFail = DefaultLintErrorMessage, 625 expectedIssues = 626 """ 627 src/test/pkg/NotDeprecatedClass.java:2: error: Extending deprecated super class class test.pkg.DeprecatedOuterClass from test.pkg.NotDeprecatedClass: this class should also be deprecated [ExtendsDeprecated] 628 src/test/pkg/NotDeprecatedClass.java:3: error: Parameter references deprecated type test.pkg.DeprecatedOuterClass in test.pkg.NotDeprecatedClass.usesDeprecatedOuterClass(): this method should also be deprecated [ReferencesDeprecated] 629 """, 630 ) 631 } 632 633 @Test Test that usage of effectively deprecated class is flaggednull634 fun `Test that usage of effectively deprecated class is flagged`() { 635 check( 636 sourceFiles = 637 arrayOf( 638 java( 639 """ 640 package test.pkg; 641 /** @deprecated */ 642 @Deprecated 643 public class DeprecatedOuterClass { 644 public class EffectivelyDeprecatedInnerClass {} 645 } 646 """ 647 ), 648 java( 649 """ 650 package test.pkg; 651 public class NotDeprecatedClass extends DeprecatedOuterClass.EffectivelyDeprecatedInnerClass { 652 public void usesEffectivelyDeprecatedInnerClass(DeprecatedOuterClass.EffectivelyDeprecatedInnerClass edic) {} 653 } 654 """ 655 ) 656 ), 657 api = 658 """ 659 package test.pkg { 660 @Deprecated public class DeprecatedOuterClass { 661 ctor @Deprecated public DeprecatedOuterClass(); 662 } 663 @Deprecated public class DeprecatedOuterClass.EffectivelyDeprecatedInnerClass { 664 ctor @Deprecated public DeprecatedOuterClass.EffectivelyDeprecatedInnerClass(); 665 } 666 public class NotDeprecatedClass extends test.pkg.DeprecatedOuterClass.EffectivelyDeprecatedInnerClass { 667 ctor public NotDeprecatedClass(); 668 method public void usesEffectivelyDeprecatedInnerClass(test.pkg.DeprecatedOuterClass.EffectivelyDeprecatedInnerClass!); 669 } 670 } 671 """, 672 extraArguments = 673 arrayOf(ARG_ERROR, "ReferencesDeprecated", ARG_ERROR, "ExtendsDeprecated"), 674 expectedFail = DefaultLintErrorMessage, 675 expectedIssues = 676 """ 677 src/test/pkg/NotDeprecatedClass.java:2: error: Extending deprecated super class class test.pkg.DeprecatedOuterClass.EffectivelyDeprecatedInnerClass from test.pkg.NotDeprecatedClass: this class should also be deprecated [ExtendsDeprecated] 678 src/test/pkg/NotDeprecatedClass.java:3: error: Parameter references deprecated type test.pkg.DeprecatedOuterClass in test.pkg.NotDeprecatedClass.usesEffectivelyDeprecatedInnerClass(): this method should also be deprecated [ReferencesDeprecated] 679 src/test/pkg/NotDeprecatedClass.java:3: error: Parameter references deprecated type test.pkg.DeprecatedOuterClass.EffectivelyDeprecatedInnerClass in test.pkg.NotDeprecatedClass.usesEffectivelyDeprecatedInnerClass(): this method should also be deprecated [ReferencesDeprecated] 680 """, 681 ) 682 } 683 684 @Test Test usage of deprecated typenull685 fun `Test usage of deprecated type `() { 686 check( 687 sourceFiles = 688 arrayOf( 689 java( 690 """ 691 package test.pkg; 692 /** @deprecated */ 693 @Deprecated 694 public class DeprecatedClass {} 695 """ 696 ), 697 java( 698 """ 699 package test.pkg; 700 import java.util.List; 701 public class NotDeprecatedClass { 702 public List<DeprecatedClass> usesDeprecated(List<DeprecatedClass> list) { 703 return list; 704 } 705 } 706 """ 707 ) 708 ), 709 api = 710 """ 711 package test.pkg { 712 @Deprecated public class DeprecatedClass { 713 ctor @Deprecated public DeprecatedClass(); 714 } 715 public class NotDeprecatedClass { 716 ctor public NotDeprecatedClass(); 717 method public java.util.List<test.pkg.DeprecatedClass!>! usesDeprecated(java.util.List<test.pkg.DeprecatedClass!>!); 718 } 719 } 720 """, 721 extraArguments = arrayOf(ARG_ERROR, "ReferencesDeprecated"), 722 expectedFail = DefaultLintErrorMessage, 723 expectedIssues = 724 """ 725 src/test/pkg/NotDeprecatedClass.java:4: error: Parameter references deprecated type test.pkg.DeprecatedClass in test.pkg.NotDeprecatedClass.usesDeprecated(): this method should also be deprecated [ReferencesDeprecated] 726 src/test/pkg/NotDeprecatedClass.java:4: error: Return type references deprecated type test.pkg.DeprecatedClass in test.pkg.NotDeprecatedClass.usesDeprecated(): this method should also be deprecated [ReferencesDeprecated] 727 """, 728 ) 729 } 730 731 @Test Test propagation of @hide through package and class nestingnull732 fun `Test propagation of @hide through package and class nesting`() { 733 // 734 check( 735 // Include system API annotations as a show annotation overrides hidden on a class that 736 // is in a hidden package. 737 includeSystemApiAnnotations = true, 738 // This is set to true so any class that is incorrectly unhidden will be included in the 739 // generated API and fail the test. 740 showUnannotated = true, 741 sourceFiles = 742 arrayOf( 743 // Package "test.a" is hidden but "test.a.B" os marked with a show annotation so 744 // that should cause "test.a" to be unhidden. However, "test.a.C" should still 745 // be hidden as it inherits that from "test.a". 746 java( 747 """ 748 /** @hide */ 749 package test.a; 750 """ 751 ), 752 java( 753 """ 754 package test.a; 755 public class A {} 756 """ 757 ), 758 java( 759 """ 760 package test.a; 761 /** @hide */ 762 @android.annotation.SystemApi 763 public class B {} 764 """ 765 ), 766 java( 767 """ 768 package test.a; 769 public class C {} 770 """ 771 ), 772 // Package "test.a.b" is not hidden itself but should inherit the hidden status 773 // of the containing package "test.a" even though test.a has been unhidden 774 // because of "test.a.B" having a show annotation. This should then be unhidden 775 // because "test.a.b.B" has a show annotation but "test.a.b.C" should still be 776 // hidden as it inherits it from "test.a". 777 java( 778 """ 779 package test.a.b; 780 public class A {} 781 """ 782 ), 783 java( 784 """ 785 package test.a.b; 786 /** @hide */ 787 @android.annotation.SystemApi 788 public class B {} 789 """ 790 ), 791 java( 792 """ 793 package test.a.b; 794 public class C {} 795 """ 796 ), 797 ), 798 api = 799 """ 800 package test.a { 801 public class B { 802 ctor public B(); 803 } 804 } 805 package test.a.b { 806 public class B { 807 ctor public B(); 808 } 809 } 810 """, 811 ) 812 } 813 } 814