xref: /aosp_15_r20/tools/metalava/metalava/src/test/java/com/android/tools/metalava/ApiAnalyzerTest.kt (revision 115816f9299ab6ddd6b9673b81f34e707f6bacab)
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