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