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 @file:Suppress("unused") 17 18 package sample.optin 19 20 /** 21 * Regression test for b/193110413 where the lint check does not handle nested annotations. 22 * 23 * This uses the Kotlin compiler's enforcement and is guaranteed to be correct. 24 */ 25 class RegressionTestKotlin193110413 { 26 @ExperimentalKotlinAnnotation 27 internal interface ExperimentalInterface { experimentalMethodnull28 fun experimentalMethod() 29 30 fun anotherExperimentalMethod() 31 32 fun defaultExperimentalMethod() { 33 // Stub! 34 } 35 } 36 37 /** Safe usage due to opting in to the experimental annotation. */ 38 @OptIn(ExperimentalKotlinAnnotation::class) 39 internal class Foo : ExperimentalInterface { 40 @Suppress("OPT_IN_MARKER_ON_OVERRIDE_WARNING") 41 @ExperimentalKotlinAnnotation experimentalMethodnull42 override fun experimentalMethod() { 43 // Stub! 44 } 45 anotherExperimentalMethodnull46 override fun anotherExperimentalMethod() { 47 // Stub! 48 } 49 stableClassLevelOptInnull50 fun stableClassLevelOptIn() { 51 // Stub! 52 } 53 } 54 55 /** Safe usage due to propagating the experimental annotation. */ 56 @ExperimentalKotlinAnnotation 57 internal class Bar : ExperimentalInterface { experimentalMethodnull58 override fun experimentalMethod() { 59 // Stub! 60 } 61 anotherExperimentalMethodnull62 override fun anotherExperimentalMethod() { 63 // Stub! 64 } 65 66 @OptIn(ExperimentalKotlinAnnotation::class) stableMethodLevelOptInnull67 fun stableMethodLevelOptIn() { 68 // Stub! 69 } 70 } 71 72 /** 73 * Unsafe call to an experimental method where the containing class has opted-in to an unstable 74 * interface, thus the constructor and stable method calls are safe. 75 * 76 * The expected behavior has been verified against the Kotlin compiler's implementation of 77 * opt-in. 78 */ regressionTestMixedStabilitynull79 fun regressionTestMixedStability() { 80 val foo = Foo() // safe 81 foo.stableClassLevelOptIn() // safe 82 foo.anotherExperimentalMethod() // safe 83 foo.defaultExperimentalMethod() // safe 84 foo.experimentalMethod() // unsafe 85 val bar = Bar() // unsafe 86 bar.stableMethodLevelOptIn() // unsafe due to class reference 87 bar.experimentalMethod() // unsafe 88 } 89 } 90