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.ProjectDescription
23 import com.android.tools.lint.checks.infrastructure.TestFile
24 import com.android.tools.lint.checks.infrastructure.TestFiles
25 import com.android.tools.lint.checks.infrastructure.TestLintResult
26 import com.android.tools.lint.checks.infrastructure.TestMode
27 import com.android.tools.lint.detector.api.Detector
28 import com.android.tools.lint.detector.api.Issue
29 import java.io.FileNotFoundException
30 
31 /** Implementation of [LintDetectorTest] that's slightly more Kotlin-friendly. */
32 abstract class AbstractLintDetectorTest(
33     val useDetector: Detector,
34     val useIssues: List<Issue>,
35     val stubs: Array<TestFile> = emptyArray(),
36 ) : LintDetectorTest() {
getDetectornull37     override fun getDetector(): Detector = useDetector
38 
39     override fun getIssues(): List<Issue> = useIssues
40 
41     /**
42      * Runs lint checks for the given [projects] using (optionally) specified [testModes].
43      *
44      * Test mode modification is available to work around issues regarding partial analysis
45      * (b/188814760, b/201086161#comment4).
46      */
47     fun check(
48         vararg projects: ProjectDescription,
49         testModes: List<TestMode> = listOf(TestMode.DEFAULT, TestMode.PARTIAL)
50     ): TestLintResult {
51         // If we have stubs, push those into a virtual project and pass them through the call to
52         // projects(), since attempting to call files() would overwrite the call to projects().
53         val projectsWithStubs =
54             if (stubs.isNotEmpty()) {
55                 arrayOf(*projects, project().files(*stubs))
56             } else {
57                 projects
58             }
59 
60         return lint().projects(*projectsWithStubs).testModes(testModes).allowDuplicates().run()
61     }
62 
checknull63     fun check(
64         vararg files: TestFile,
65     ): TestLintResult {
66         return lint().files(*stubs, *files).allowDuplicates().run()
67     }
68 }
69 
70 /** Creates a new [ProjectDescription]. */
projectnull71 fun project(): ProjectDescription = ProjectDescription()
72 
73 /** Loads a [TestFile] from `AndroidManifest.xml` included in the JAR resources. */
74 fun manifestSample(): TestFile =
75     TestFiles.manifest(
76         Stubs::class.java.getResource("/AndroidManifest.xml")?.readText()
77             ?: throw FileNotFoundException(
78                 "Could not find AndroidManifest.xml in the integration test project"
79             )
80     )
81 
82 /** Loads a [TestFile] from Java source code included in the JAR resources. */
83 fun javaSample(className: String): TestFile =
84     TestFiles.java(
85         Stubs::class.java.getResource("/java/${className.replace('.', '/')}.java")?.readText()
86             ?: throw FileNotFoundException(
87                 "Could not find Java sources for $className in the integration test project"
88             )
89     )
90 
91 /** Loads a [TestFile] from Kotlin source code included in the JAR resources. */
92 fun ktSample(className: String): TestFile =
93     TestFiles.kotlin(
94         Stubs::class.java.getResource("/java/${className.replace('.', '/')}.kt")?.readText()
95             ?: throw FileNotFoundException(
96                 "Could not find Kotlin sources for $className in the integration test project"
97             )
98     )
99