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 @file:Suppress("UnstableApiUsage")
18 
19 package androidx.build.lint
20 
21 import com.android.tools.lint.checks.infrastructure.LintDetectorTest
22 import com.android.tools.lint.checks.infrastructure.TestFile
23 import com.android.tools.lint.checks.infrastructure.TestLintTask
24 import com.android.tools.lint.detector.api.Detector
25 import com.android.tools.lint.detector.api.Issue
26 import org.junit.Test
27 
28 class TargetApiAnnotationUsageDetectorTest : LintDetectorTest() {
getDetectornull29     override fun getDetector(): Detector = TargetApiAnnotationUsageDetector()
30 
31     override fun getIssues(): List<Issue> = listOf(TargetApiAnnotationUsageDetector.ISSUE)
32 
33     private fun checkTask(testFile: TestFile): TestLintTask {
34         return lint().files(java(annotationSource), testFile)
35     }
36 
37     private val annotationSource =
38         """
39 package android.annotation;
40 
41 import static java.lang.annotation.ElementType.CONSTRUCTOR;
42 import static java.lang.annotation.ElementType.METHOD;
43 import static java.lang.annotation.ElementType.TYPE;
44 
45 import java.lang.annotation.Retention;
46 import java.lang.annotation.RetentionPolicy;
47 import java.lang.annotation.Target;
48 
49 @Target({TYPE, METHOD, CONSTRUCTOR})
50 @Retention(RetentionPolicy.CLASS)
51 public @interface TargetApi {
52     int value();
53 }
54     """
55             .trimIndent()
56 
57     @Test
testAnnotationUsageJavanull58     fun testAnnotationUsageJava() {
59         val input =
60             java(
61                 """
62 package androidx.sample;
63 
64 import android.annotation.TargetApi;
65 
66 @TargetApi(24)
67 public class SampleClass {
68     @TargetApi(15)
69     public void method() {
70         // Stub
71     }
72 }
73             """
74                     .trimIndent()
75             )
76 
77         val expected =
78             """
79 src/androidx/sample/SampleClass.java:5: Error: Use @RequiresApi instead of @TargetApi [BanTargetApiAnnotation]
80 @TargetApi(24)
81 ~~~~~~~~~~~~~~
82 src/androidx/sample/SampleClass.java:7: Error: Use @RequiresApi instead of @TargetApi [BanTargetApiAnnotation]
83     @TargetApi(15)
84     ~~~~~~~~~~~~~~
85 2 errors, 0 warnings
86         """
87                 .trimIndent()
88 
89         val expectFixDiffs =
90             """
91 Fix for src/androidx/sample/SampleClass.java line 5: Replace with `@RequiresApi`:
92 @@ -5 +5
93 - @TargetApi(24)
94 + @androidx.annotation.RequiresApi(24)
95 Fix for src/androidx/sample/SampleClass.java line 7: Replace with `@RequiresApi`:
96 @@ -7 +7
97 -     @TargetApi(15)
98 +     @androidx.annotation.RequiresApi(15)
99         """
100                 .trimIndent()
101 
102         checkTask(input).run().expect(expected).expectFixDiffs(expectFixDiffs)
103     }
104 
105     @Test
testAnnotationUsageKtnull106     fun testAnnotationUsageKt() {
107         val input =
108             kotlin(
109                 """
110 package androidx.sample
111 
112 import android.annotation.TargetApi
113 
114 @TargetApi(24)
115 class SampleClass {
116     @TargetApi(15)
117     fun method() {
118         // Stub
119     }
120 }
121             """
122                     .trimIndent()
123             )
124 
125         val expected =
126             """
127 src/androidx/sample/SampleClass.kt:5: Error: Use @RequiresApi instead of @TargetApi [BanTargetApiAnnotation]
128 @TargetApi(24)
129 ~~~~~~~~~~~~~~
130 src/androidx/sample/SampleClass.kt:7: Error: Use @RequiresApi instead of @TargetApi [BanTargetApiAnnotation]
131     @TargetApi(15)
132     ~~~~~~~~~~~~~~
133 2 errors, 0 warnings
134         """
135                 .trimIndent()
136 
137         val expectFixDiffs =
138             """
139 Fix for src/androidx/sample/SampleClass.kt line 5: Replace with `@RequiresApi`:
140 @@ -5 +5
141 - @TargetApi(24)
142 + @androidx.annotation.RequiresApi(24)
143 Fix for src/androidx/sample/SampleClass.kt line 7: Replace with `@RequiresApi`:
144 @@ -7 +7
145 -     @TargetApi(15)
146 +     @androidx.annotation.RequiresApi(15)
147         """
148                 .trimIndent()
149 
150         checkTask(input).run().expect(expected).expectFixDiffs(expectFixDiffs)
151     }
152 }
153