Clean up TargetApiAnnotationUsageDetector, add lint fix

Fixes suppression in slice-view library and compose test-utils.

Fixes: 187503648
Test: TargetApiAnnotationUsageDetectorTest
Change-Id: I09189013af457f23691f55aa74076bef6a5075db
diff --git a/compose/test-utils/src/androidMain/kotlin/androidx/compose/testutils/AndroidComposeTestCaseRunner.android.kt b/compose/test-utils/src/androidMain/kotlin/androidx/compose/testutils/AndroidComposeTestCaseRunner.android.kt
index fe28c00..2275c67 100644
--- a/compose/test-utils/src/androidMain/kotlin/androidx/compose/testutils/AndroidComposeTestCaseRunner.android.kt
+++ b/compose/test-utils/src/androidMain/kotlin/androidx/compose/testutils/AndroidComposeTestCaseRunner.android.kt
@@ -16,7 +16,6 @@
 
 package androidx.compose.testutils
 
-import android.annotation.TargetApi
 import android.app.Activity
 import android.graphics.Bitmap
 import android.graphics.Canvas
@@ -28,6 +27,7 @@
 import android.view.View
 import android.view.ViewGroup
 import android.widget.ImageView
+import androidx.annotation.RequiresApi
 import androidx.activity.ComponentActivity
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionContext
@@ -79,6 +79,8 @@
 
     private val screenWithSpec: Int
     private val screenHeightSpec: Int
+
+    @Suppress("NewApi") // NewApi doesn't understand Kotlin `when` (b/189459502)
     private val capture = when {
         supportsRenderNode -> RenderNodeCapture()
         supportsMRenderNode -> MRenderNodeCapture()
@@ -342,7 +344,7 @@
     fun endRecording()
 }
 
-@TargetApi(Build.VERSION_CODES.Q)
+@RequiresApi(Build.VERSION_CODES.Q)
 private class RenderNodeCapture : DrawCapture {
     private val renderNode = RenderNode("Test")
 
diff --git a/fragment/integration-tests/testapp/lint-baseline.xml b/fragment/integration-tests/testapp/lint-baseline.xml
deleted file mode 100644
index 64d6c6c..0000000
--- a/fragment/integration-tests/testapp/lint-baseline.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.0.0-alpha15" type="baseline" client="cli" name="Lint" variant="all" version="7.0.0-alpha15">
-
-    <issue
-        id="BanTargetApiAnnotation"
-        message="Uses @TargetApi annotation"
-        errorLine1="@TargetApi(Build.VERSION_CODES.LOLLIPOP)"
-        errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/fragment/testapp/kittenfragmenttransitions/DetailsTransition.kt"
-            line="31"
-            column="1"/>
-    </issue>
-
-</issues>
diff --git a/fragment/integration-tests/testapp/src/main/java/androidx/fragment/testapp/kittenfragmenttransitions/DetailsTransition.kt b/fragment/integration-tests/testapp/src/main/java/androidx/fragment/testapp/kittenfragmenttransitions/DetailsTransition.kt
index ee8f55d..3d1826c 100644
--- a/fragment/integration-tests/testapp/src/main/java/androidx/fragment/testapp/kittenfragmenttransitions/DetailsTransition.kt
+++ b/fragment/integration-tests/testapp/src/main/java/androidx/fragment/testapp/kittenfragmenttransitions/DetailsTransition.kt
@@ -15,10 +15,10 @@
  */
 package androidx.fragment.testapp.kittenfragmenttransitions
 
-import android.annotation.TargetApi
 import android.content.Context
 import android.os.Build
 import android.util.AttributeSet
+import androidx.annotation.RequiresApi
 import androidx.transition.ChangeBounds
 import androidx.transition.ChangeImageTransform
 import androidx.transition.ChangeTransform
@@ -28,7 +28,7 @@
  * Transition that performs almost exactly like [android.transition.AutoTransition], but has
  * an added [ChangeImageTransform] to support properly scaling up our gorgeous kittens.
  */
-@TargetApi(Build.VERSION_CODES.LOLLIPOP)
+@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
 class DetailsTransition : TransitionSet {
     constructor() {
         init()
diff --git a/lint-checks/src/main/java/androidx/build/lint/AndroidXIssueRegistry.kt b/lint-checks/src/main/java/androidx/build/lint/AndroidXIssueRegistry.kt
index 60769c1..6f93b40 100644
--- a/lint-checks/src/main/java/androidx/build/lint/AndroidXIssueRegistry.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/AndroidXIssueRegistry.kt
@@ -36,7 +36,7 @@
                 BanConcurrentHashMap.ISSUE,
                 BanInappropriateExperimentalUsage.ISSUE,
                 BanKeepAnnotation.ISSUE,
-                BanTargetApiAnnotation.ISSUE,
+                TargetApiAnnotationUsageDetector.ISSUE,
                 SampledAnnotationEnforcer.MISSING_SAMPLED_ANNOTATION,
                 SampledAnnotationEnforcer.OBSOLETE_SAMPLED_ANNOTATION,
                 SampledAnnotationEnforcer.MISSING_SAMPLES_DIRECTORY,
diff --git a/lint-checks/src/main/java/androidx/build/lint/BanTargetApiAnnotation.kt b/lint-checks/src/main/java/androidx/build/lint/TargetApiAnnotationUsageDetector.kt
similarity index 63%
rename from lint-checks/src/main/java/androidx/build/lint/BanTargetApiAnnotation.kt
rename to lint-checks/src/main/java/androidx/build/lint/TargetApiAnnotationUsageDetector.kt
index b6e8e0b..4e9fd59 100644
--- a/lint-checks/src/main/java/androidx/build/lint/BanTargetApiAnnotation.kt
+++ b/lint-checks/src/main/java/androidx/build/lint/TargetApiAnnotationUsageDetector.kt
@@ -29,7 +29,10 @@
 import com.android.tools.lint.detector.api.Severity
 import org.jetbrains.uast.UAnnotation
 
-class BanTargetApiAnnotation : Detector(), Detector.UastScanner {
+/**
+ * Enforces policy banning use of the `@TargetApi` annotation.
+ */
+class TargetApiAnnotationUsageDetector : Detector(), Detector.UastScanner {
 
     override fun getApplicableUastTypes() = listOf(UAnnotation::class.java)
 
@@ -42,7 +45,14 @@
             if (node.qualifiedName == "android.annotation.TargetApi") {
                 context.report(
                     ISSUE, node, context.getNameLocation(node),
-                    "Uses @TargetApi annotation"
+                    "Use `@RequiresApi` instead of `@TargetApi`",
+                    fix().name("Replace with `@RequiresApi`")
+                        .replace()
+                        .pattern("(?:android\\.annotation\\.)?TargetApi")
+                        .with("androidx.annotation.RequiresApi")
+                        .shortenNames()
+                        .autoFix(true, true)
+                        .build(),
                 )
             }
         }
@@ -51,11 +61,13 @@
     companion object {
         val ISSUE = Issue.create(
             "BanTargetApiAnnotation",
-            "Uses @TargetApi annotation",
-            "Use of @TargetApi annotation is not allowed, please consider " +
-                "using the @RequiresApi annotation instead.",
+            "Replace usage of `@TargetApi` with `@RequiresApi`",
+            "The `@TargetApi` annotation satisfies the `NewApi` lint check, but it does " +
+                "not ensure that calls to the annotated API are correctly guarded on an `SDK_INT`" +
+                " (or equivalent) check. Instead, use the `@RequiresApi` annotation to ensure " +
+                "that all calls are correctly guarded.",
             Category.CORRECTNESS, 5, Severity.ERROR,
-            Implementation(BanTargetApiAnnotation::class.java, Scope.JAVA_FILE_SCOPE)
+            Implementation(TargetApiAnnotationUsageDetector::class.java, Scope.JAVA_FILE_SCOPE)
         )
     }
 }
diff --git a/lint-checks/src/test/java/androidx/build/lint/BanTargetApiAnnotationTest.kt b/lint-checks/src/test/java/androidx/build/lint/TargetApiAnnotationDetectorTest.kt
similarity index 75%
rename from lint-checks/src/test/java/androidx/build/lint/BanTargetApiAnnotationTest.kt
rename to lint-checks/src/test/java/androidx/build/lint/TargetApiAnnotationDetectorTest.kt
index 49429e0..5ccf192 100644
--- a/lint-checks/src/test/java/androidx/build/lint/BanTargetApiAnnotationTest.kt
+++ b/lint-checks/src/test/java/androidx/build/lint/TargetApiAnnotationDetectorTest.kt
@@ -23,9 +23,9 @@
 import org.junit.runners.JUnit4
 
 @RunWith(JUnit4::class)
-class BanTargetApiAnnotationTest : AbstractLintDetectorTest(
-    useDetector = BanTargetApiAnnotation(),
-    useIssues = listOf(BanTargetApiAnnotation.ISSUE),
+class TargetApiAnnotationDetectorTest : AbstractLintDetectorTest(
+    useDetector = TargetApiAnnotationUsageDetector(),
+    useIssues = listOf(TargetApiAnnotationUsageDetector.ISSUE),
 ) {
 
     @Test
@@ -36,10 +36,10 @@
 
         /* ktlint-disable max-line-length */
         val expected = """
-src/androidx/TargetApiUsageJava.java:22: Error: Uses @TargetApi annotation [BanTargetApiAnnotation]
+src/androidx/TargetApiUsageJava.java:22: Error: Use @RequiresApi instead of @TargetApi [BanTargetApiAnnotation]
 @TargetApi(29)
 ~~~~~~~~~~~~~~
-src/androidx/TargetApiUsageJava.java:25: Error: Uses @TargetApi annotation [BanTargetApiAnnotation]
+src/androidx/TargetApiUsageJava.java:25: Error: Use @RequiresApi instead of @TargetApi [BanTargetApiAnnotation]
     @TargetApi(30)
     ~~~~~~~~~~~~~~
 2 errors, 0 warnings
diff --git a/lint-checks/src/test/java/androidx/build/lint/TargetApiAnnotationUsageDetectorTest.kt b/lint-checks/src/test/java/androidx/build/lint/TargetApiAnnotationUsageDetectorTest.kt
new file mode 100644
index 0000000..5bf4605
--- /dev/null
+++ b/lint-checks/src/test/java/androidx/build/lint/TargetApiAnnotationUsageDetectorTest.kt
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:Suppress("UnstableApiUsage")
+
+package androidx.build.lint
+
+import com.android.tools.lint.checks.infrastructure.LintDetectorTest
+import com.android.tools.lint.checks.infrastructure.TestFile
+import com.android.tools.lint.checks.infrastructure.TestLintResult
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+
+import org.junit.Test
+
+class TargetApiAnnotationUsageDetectorTest : LintDetectorTest() {
+    override fun getDetector(): Detector = TargetApiAnnotationUsageDetector()
+
+    override fun getIssues(): List<Issue> = listOf(
+        TargetApiAnnotationUsageDetector.ISSUE
+    )
+
+    private fun check(testFile: TestFile): TestLintResult {
+        return lint().files(
+            java(annotationSource),
+            testFile
+        ).run()
+    }
+
+    private val annotationSource = """
+package android.annotation;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({TYPE, METHOD, CONSTRUCTOR})
+@Retention(RetentionPolicy.CLASS)
+public @interface TargetApi {
+    int value();
+}
+    """.trimIndent()
+
+    @Test
+    fun testAnnotationUsageJava() {
+        val input = java(
+            """
+package androidx.sample;
+
+import android.annotation.TargetApi;
+
+@TargetApi(24)
+public class SampleClass {
+    @TargetApi(15)
+    public void method() {
+        // Stub
+    }
+}
+            """.trimIndent()
+        )
+
+        /* ktlint-disable max-line-length */
+        val expected = """
+src/androidx/sample/SampleClass.java:5: Error: Use @RequiresApi instead of @TargetApi [BanTargetApiAnnotation]
+@TargetApi(24)
+~~~~~~~~~~~~~~
+src/androidx/sample/SampleClass.java:7: Error: Use @RequiresApi instead of @TargetApi [BanTargetApiAnnotation]
+    @TargetApi(15)
+    ~~~~~~~~~~~~~~
+2 errors, 0 warnings
+        """.trimIndent()
+        /* ktlint-enable max-line-length */
+
+        /* ktlint-disable max-line-length */
+        val expectFixDiffs = """
+Fix for src/androidx/sample/SampleClass.java line 5: Replace with `@RequiresApi`:
+@@ -5 +5
+- @TargetApi(24)
++ @androidx.annotation.RequiresApi(24)
+Fix for src/androidx/sample/SampleClass.java line 7: Replace with `@RequiresApi`:
+@@ -7 +7
+-     @TargetApi(15)
++     @androidx.annotation.RequiresApi(15)
+        """.trimIndent()
+        /* ktlint-enable max-line-length */
+
+        check(input)
+            .expect(expected)
+            .expectFixDiffs(expectFixDiffs)
+    }
+
+    @Test
+    fun testAnnotationUsageKt() {
+        val input = kotlin(
+            """
+package androidx.sample
+
+import android.annotation.TargetApi
+
+@TargetApi(24)
+class SampleClass {
+    @TargetApi(15)
+    fun method() {
+        // Stub
+    }
+}
+            """.trimIndent()
+        )
+
+        /* ktlint-disable max-line-length */
+        val expected = """
+src/androidx/sample/SampleClass.kt:5: Error: Use @RequiresApi instead of @TargetApi [BanTargetApiAnnotation]
+@TargetApi(24)
+~~~~~~~~~~~~~~
+src/androidx/sample/SampleClass.kt:7: Error: Use @RequiresApi instead of @TargetApi [BanTargetApiAnnotation]
+    @TargetApi(15)
+    ~~~~~~~~~~~~~~
+2 errors, 0 warnings
+        """.trimIndent()
+        /* ktlint-enable max-line-length */
+
+        /* ktlint-disable max-line-length */
+        val expectFixDiffs = """
+Fix for src/androidx/sample/SampleClass.kt line 5: Replace with `@RequiresApi`:
+@@ -5 +5
+- @TargetApi(24)
++ @androidx.annotation.RequiresApi(24)
+Fix for src/androidx/sample/SampleClass.kt line 7: Replace with `@RequiresApi`:
+@@ -7 +7
+-     @TargetApi(15)
++     @androidx.annotation.RequiresApi(15)
+        """.trimIndent()
+        /* ktlint-enable max-line-length */
+
+        check(input)
+            .expect(expected)
+            .expectFixDiffs(expectFixDiffs)
+    }
+}
diff --git a/slices/view/lint-baseline.xml b/slices/view/lint-baseline.xml
index 3ee1112..6642ebe 100644
--- a/slices/view/lint-baseline.xml
+++ b/slices/view/lint-baseline.xml
@@ -13,17 +13,6 @@
     </issue>
 
     <issue
-        id="BanTargetApiAnnotation"
-        message="Uses @TargetApi annotation"
-        errorLine1="    @TargetApi(Build.VERSION_CODES.LOLLIPOP)"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="src/main/java/androidx/slice/widget/LocationBasedViewTracker.java"
-            line="47"
-            column="5"/>
-    </issue>
-
-    <issue
         id="ClassVerificationFailure"
         message="This call references a method added in API level 20; however, the containing class androidx.slice.widget.ActionRow is reachable from earlier API levels and will fail run-time class verification."
         errorLine1="        if (input.getRemoteInput().getAllowFreeFormInput()) {"
diff --git a/slices/view/src/main/java/androidx/slice/widget/LocationBasedViewTracker.java b/slices/view/src/main/java/androidx/slice/widget/LocationBasedViewTracker.java
index a35b944..b1b3c18 100644
--- a/slices/view/src/main/java/androidx/slice/widget/LocationBasedViewTracker.java
+++ b/slices/view/src/main/java/androidx/slice/widget/LocationBasedViewTracker.java
@@ -18,7 +18,6 @@
 
 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS;
 
-import android.annotation.TargetApi;
 import android.content.Context;
 import android.graphics.Rect;
 import android.os.Build;
@@ -26,6 +25,7 @@
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityManager;
 
+import androidx.annotation.RequiresApi;
 import androidx.annotation.RestrictTo;
 
 import java.util.ArrayList;
@@ -44,7 +44,7 @@
         }
     };
 
-    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
     private static final SelectionLogic A11Y_FOCUS = new SelectionLogic() {
         @Override
         public void selectView(View view) {