1 /*
2  * Copyright 2021 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 sample.optin;
18 
19 import androidx.annotation.OptIn;
20 
21 /**
22  * Regression test for b/193110413 where the lint check does not handle nested annotations.
23  */
24 @SuppressWarnings("unused")
25 public class RegressionTestJava193110413 {
26 
27     @ExperimentalJavaAnnotation
28     interface ExperimentalInterface {
experimentalMethod()29         void experimentalMethod();
anotherExperimentalMethod()30         void anotherExperimentalMethod();
31 
defaultExperimentalMethod()32         default void defaultExperimentalMethod() {
33             // Stub!
34         }
35     }
36 
37     /**
38      * Safe usage due to opting in to the experimental annotation.
39      */
40     @OptIn(markerClass = ExperimentalJavaAnnotation.class)
41     static class Foo implements ExperimentalInterface {
42 
43         @ExperimentalJavaAnnotation
44         @Override
experimentalMethod()45         public void experimentalMethod() {
46             // Stub!
47         }
48 
49         @Override
anotherExperimentalMethod()50         public void anotherExperimentalMethod() {
51             // Stub!
52         }
53 
stableClassLevelOptIn()54         public void stableClassLevelOptIn() {
55             // Stub!
56         }
57     }
58 
59     /**
60      * Safe usage due to propagating the experimental annotation.
61      */
62     @ExperimentalJavaAnnotation
63     static class Bar implements ExperimentalInterface {
64 
65         @Override
experimentalMethod()66         public void experimentalMethod() {
67             // Stub!
68         }
69 
70         @Override
anotherExperimentalMethod()71         public void anotherExperimentalMethod() {
72             // Stub!
73         }
74 
75         @OptIn(markerClass = ExperimentalJavaAnnotation.class)
stableMethodLevelOptIn()76         public void stableMethodLevelOptIn() {
77             // Stub!
78         }
79     }
80 
81     /**
82      * Unsafe call to an experimental method where the containing class has opted-in to an
83      * unstable interface, thus the constructor and stable method calls are safe.
84      *
85      * The expected behavior has been verified against the Kotlin compiler's implementation of
86      * opt-in.
87      */
regressionTestMixedStability()88     void regressionTestMixedStability() {
89         Foo foo = new Foo(); // safe
90         foo.stableClassLevelOptIn(); // safe
91         foo.anotherExperimentalMethod(); // safe
92         foo.defaultExperimentalMethod(); // unsafe in Java but safe in Kotlin
93         foo.experimentalMethod(); // unsafe
94 
95         Bar bar = new Bar(); // unsafe
96         bar.stableMethodLevelOptIn(); // unsafe due to experimental class scope
97         bar.experimentalMethod(); // unsafe
98     }
99 }
100