Add lint detector for imports of internal Gradle and AGP APIs
Test: new tests + updating lint for existing Gradle code
Bug: 324318516
Change-Id: Ib3fc2066caec980311bfde66ef180dfa828c8b41
diff --git a/benchmark/baseline-profile-gradle-plugin/lint-baseline.xml b/benchmark/baseline-profile-gradle-plugin/lint-baseline.xml
new file mode 100644
index 0000000..5c2583a
--- /dev/null
+++ b/benchmark/baseline-profile-gradle-plugin/lint-baseline.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.4.0-alpha09" type="baseline" client="gradle" dependencies="false" name="AGP (8.4.0-alpha09)" variant="all" version="8.4.0-alpha09">
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Android Gradle Plugin APIs"
+ errorLine1="import com.android.build.gradle.internal.api.DefaultAndroidSourceDirectorySet"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/kotlin/androidx/baselineprofile/gradle/utils/BuildTypes.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Android Gradle Plugin APIs"
+ errorLine1="import com.android.build.gradle.internal.api.DefaultAndroidSourceFile"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/kotlin/androidx/baselineprofile/gradle/utils/BuildTypes.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Android Gradle Plugin APIs"
+ errorLine1="import com.android.build.gradle.internal.tasks.BuildAnalyzer"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/kotlin/androidx/baselineprofile/gradle/producer/tasks/CollectBaselineProfileTask.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Android Gradle Plugin APIs"
+ errorLine1="import com.android.build.gradle.internal.tasks.BuildAnalyzer"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/kotlin/androidx/baselineprofile/gradle/consumer/task/GenerateBaselineProfileTask.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Android Gradle Plugin APIs"
+ errorLine1="import com.android.build.gradle.internal.tasks.BuildAnalyzer"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/kotlin/androidx/baselineprofile/gradle/apptarget/task/GenerateKeepRulesForBaselineProfilesTask.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Android Gradle Plugin APIs"
+ errorLine1="import com.android.build.gradle.internal.tasks.BuildAnalyzer"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/kotlin/androidx/baselineprofile/gradle/consumer/task/MergeBaselineProfileTask.kt"/>
+ </issue>
+
+</issues>
diff --git a/buildSrc-tests/lint-baseline.xml b/buildSrc-tests/lint-baseline.xml
index c00bbf9..9ee6f5b 100644
--- a/buildSrc-tests/lint-baseline.xml
+++ b/buildSrc-tests/lint-baseline.xml
@@ -352,4 +352,220 @@
file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/testConfiguration/TestSuiteConfiguration.kt"/>
</issue>
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Gradle APIs"
+ errorLine1="import org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/buildInfo/CreateLibraryBuildInfoFileTask.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Gradle APIs"
+ errorLine1="import org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependencyConstraint"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/buildInfo/CreateLibraryBuildInfoFileTask.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Gradle APIs"
+ errorLine1="import org.gradle.api.internal.artifacts.ivyservice.projectmodule.ProjectComponentPublication"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/buildInfo/CreateLibraryBuildInfoFileTask.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Gradle APIs"
+ errorLine1="import org.gradle.api.internal.component.SoftwareComponentInternal"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/buildInfo/CreateLibraryBuildInfoFileTask.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Gradle APIs"
+ errorLine1="import org.gradle.api.publish.maven.internal.publication.MavenPublicationInternal"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/buildInfo/CreateLibraryBuildInfoFileTask.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Gradle APIs"
+ errorLine1="import org.gradle.internal.logging.slf4j.OutputEventListenerBackedLogger"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/dependencyTracker/FileLogger.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Gradle APIs"
+ errorLine1="import org.gradle.internal.logging.slf4j.OutputEventListenerBackedLoggerContext"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/dependencyTracker/FileLogger.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Gradle APIs"
+ errorLine1="import org.gradle.internal.time.Clock"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/dependencyTracker/FileLogger.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Gradle APIs"
+ errorLine1="import org.gradle.internal.component.external.model.DefaultModuleComponentIdentifier"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/dackka/GenerateMetadataTask.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Android Gradle Plugin APIs"
+ errorLine1="import com.android.build.gradle.internal.lint.AndroidLintAnalysisTask"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/LintConfiguration.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Android Gradle Plugin APIs"
+ errorLine1="import com.android.build.gradle.internal.lint.LintModelWriterTask"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/LintConfiguration.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Android Gradle Plugin APIs"
+ errorLine1="import com.android.build.gradle.internal.lint.VariantInputs"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/LintConfiguration.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Gradle APIs"
+ errorLine1="import org.gradle.api.internal.component.SoftwareComponentInternal"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/MavenUploadHelper.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Gradle APIs"
+ errorLine1="import org.gradle.api.internal.component.UsageContext"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/MavenUploadHelper.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Gradle APIs"
+ errorLine1="import org.gradle.api.publish.maven.internal.publication.MavenPublicationInternal"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/MavenUploadHelper.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Gradle APIs"
+ errorLine1="import org.gradle.api.internal.artifacts.ivyservice.DefaultLenientConfiguration"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/metalava/RegenerateOldApisTask.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Gradle APIs"
+ errorLine1="import org.gradle.api.internal.tasks.userinput.UserInputHandler"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/studio/StudioTask.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Gradle APIs"
+ errorLine1="import org.gradle.internal.service.ServiceRegistry"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/studio/StudioTask.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Android Gradle Plugin APIs"
+ errorLine1="import com.android.build.gradle.internal.attributes.VariantAttr"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/testConfiguration/TestSuiteConfiguration.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Android Gradle Plugin APIs"
+ errorLine1="import com.android.build.gradle.internal.publishing.AndroidArtifacts"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/testConfiguration/TestSuiteConfiguration.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Android Gradle Plugin APIs"
+ errorLine1="import com.android.build.gradle.internal.publishing.AndroidArtifacts.ArtifactType"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/testConfiguration/TestSuiteConfiguration.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Gradle APIs"
+ errorLine1="import org.gradle.internal.logging.slf4j.OutputEventListenerBackedLogger"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/dependencyTracker/ToStringLogger.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Gradle APIs"
+ errorLine1="import org.gradle.internal.logging.slf4j.OutputEventListenerBackedLoggerContext"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/dependencyTracker/ToStringLogger.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Gradle APIs"
+ errorLine1="import org.gradle.internal.time.Clock"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="${:buildSrc-tests*main*MAIN*sourceProvider*0*javaDir*4}/androidx/build/dependencyTracker/ToStringLogger.kt"/>
+ </issue>
+
</issues>
diff --git a/lint/lint-gradle/src/main/java/androidx/lint/gradle/GradleIssueRegistry.kt b/lint/lint-gradle/src/main/java/androidx/lint/gradle/GradleIssueRegistry.kt
index bdc7136..1f720cb 100644
--- a/lint/lint-gradle/src/main/java/androidx/lint/gradle/GradleIssueRegistry.kt
+++ b/lint/lint-gradle/src/main/java/androidx/lint/gradle/GradleIssueRegistry.kt
@@ -28,6 +28,7 @@
override val issues = listOf(
EagerConfigurationDetector.ISSUE,
+ InternalApiUsageDetector.ISSUE,
)
override val vendor = Vendor(
diff --git a/lint/lint-gradle/src/main/java/androidx/lint/gradle/InternalApiUsageDetector.kt b/lint/lint-gradle/src/main/java/androidx/lint/gradle/InternalApiUsageDetector.kt
new file mode 100644
index 0000000..5e1b881
--- /dev/null
+++ b/lint/lint-gradle/src/main/java/androidx/lint/gradle/InternalApiUsageDetector.kt
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2024 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.
+ */
+
+package androidx.lint.gradle
+
+import com.android.tools.lint.client.api.UElementHandler
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Incident
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import com.intellij.psi.PsiClass
+import com.intellij.psi.PsiField
+import com.intellij.psi.PsiMethod
+import org.jetbrains.uast.UElement
+import org.jetbrains.uast.UImportStatement
+
+class InternalApiUsageDetector : Detector(), Detector.UastScanner {
+ override fun getApplicableUastTypes(): List<Class<out UElement>> = listOf(
+ UImportStatement::class.java,
+ )
+
+ override fun createUastHandler(context: JavaContext): UElementHandler = object :
+ UElementHandler() {
+ override fun visitImportStatement(node: UImportStatement) {
+ if (node.importReference != null) {
+ var resolved = node.resolve()
+ if (resolved is PsiField) {
+ resolved = resolved.containingClass
+ } else if (resolved is PsiMethod) {
+ resolved = resolved.containingClass
+ }
+
+ if (resolved is PsiClass) {
+ if (resolved.isInternalGradleApi()) {
+ reportIncidentForNode(node, "Avoid using internal Gradle APIs")
+ } else if (resolved.isInternalAgpApi()) {
+ reportIncidentForNode(
+ node,
+ "Avoid using internal Android Gradle Plugin APIs"
+ )
+ }
+ }
+ }
+ }
+
+ private fun reportIncidentForNode(node: UElement, message: String) {
+ val incident = Incident(context)
+ .issue(ISSUE)
+ .location(context.getLocation(node))
+ .message(message)
+ .scope(node)
+ context.report(incident)
+ }
+
+ private fun PsiClass.isInternalGradleApi(): Boolean {
+ val className = qualifiedName ?: return false
+ return className.startsWith("org.gradle.") && className.contains(".internal.")
+ }
+
+ private fun PsiClass.isInternalAgpApi(): Boolean {
+ val className = qualifiedName ?: return false
+ return className.startsWith("com.android.build.") && className.contains(".internal.")
+ }
+ }
+
+ companion object {
+ val ISSUE = Issue.create(
+ "InternalGradleApiUsage",
+ "Avoid using internal Gradle APIs",
+ """
+ Using internal APIs results in fragile plugin behavior as these types have no binary
+ compatibility guarantees. It is best to create a feature request to open up these
+ APIs if you find them useful.
+ """,
+ Category.CORRECTNESS, 5, Severity.ERROR,
+ Implementation(
+ InternalApiUsageDetector::class.java,
+ Scope.JAVA_FILE_SCOPE
+ )
+ )
+ }
+}
diff --git a/lint/lint-gradle/src/test/java/androidx/lint/gradle/InternalApiUsageDetectorTest.kt b/lint/lint-gradle/src/test/java/androidx/lint/gradle/InternalApiUsageDetectorTest.kt
new file mode 100644
index 0000000..23a8918
--- /dev/null
+++ b/lint/lint-gradle/src/test/java/androidx/lint/gradle/InternalApiUsageDetectorTest.kt
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2024 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.
+ */
+
+package androidx.lint.gradle
+
+import com.android.tools.lint.checks.infrastructure.TestMode
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class InternalApiUsageDetectorTest : GradleLintDetectorTest(
+ detector = InternalApiUsageDetector(),
+ issues = listOf(InternalApiUsageDetector.ISSUE)
+) {
+ @Test
+ fun `Test usage of internal Gradle API`() {
+ val input = kotlin(
+ """
+ import org.gradle.api.component.SoftwareComponent
+ import org.gradle.api.internal.component.SoftwareComponentInternal
+
+ fun getSoftwareComponent() : SoftwareComponent {
+ return object : SoftwareComponentInternal {
+ override fun getUsages(): Set<out UsageContext> {
+ TODO()
+ }
+ }
+ }
+ """.trimIndent()
+ )
+
+ lint()
+ .files(*STUBS, input)
+ // Adding import aliases adds new warnings and that is working as intended.
+ .skipTestModes(TestMode.IMPORT_ALIAS)
+ .run()
+ .expect(
+ """
+ src/test.kt:2: Error: Avoid using internal Gradle APIs [InternalGradleApiUsage]
+ import org.gradle.api.internal.component.SoftwareComponentInternal
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 1 errors, 0 warnings
+ """.trimIndent()
+ )
+
+ lint()
+ .files(*STUBS, input)
+ // Adding import aliases adds new warnings and that is working as intended.
+ .testModes(TestMode.IMPORT_ALIAS)
+ .run()
+ .expect(
+ """
+ src/test.kt:2: Error: Avoid using internal Gradle APIs [InternalGradleApiUsage]
+ import org.gradle.api.internal.component.SoftwareComponentInternal
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ src/test.kt:4: Error: Avoid using internal Gradle APIs [InternalGradleApiUsage]
+ import org.gradle.api.internal.component.SoftwareComponentInternal as IMPORT_ALIAS_2_SOFTWARECOMPONENTINTERNAL
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 2 errors, 0 warnings
+ """.trimIndent()
+ )
+ }
+
+ @Test
+ fun `Test usage of internal Android Gradle API`() {
+ val input = kotlin(
+ """
+ import com.android.build.gradle.internal.lint.VariantInputs
+ """.trimIndent()
+ )
+
+ lint()
+ .files(*STUBS, input)
+ // Import aliases mode is covered by other tests
+ .skipTestModes(TestMode.IMPORT_ALIAS)
+ .run()
+ .expect(
+ """
+ src/test.kt:1: Error: Avoid using internal Android Gradle Plugin APIs [InternalGradleApiUsage]
+ import com.android.build.gradle.internal.lint.VariantInputs
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ 1 errors, 0 warnings
+ """.trimIndent()
+ )
+ }
+
+ @Test
+ fun `Test usage of Internal annotation`() {
+ val input = kotlin(
+ """
+ import java.io.File
+ import org.gradle.api.Task
+ import org.gradle.api.tasks.Internal
+
+ class MyTask : Task {
+ @get:Internal
+ val notInput: File
+ }
+ """.trimIndent()
+ )
+ check(input).expectClean()
+ }
+}
diff --git a/lint/lint-gradle/src/test/java/androidx/lint/gradle/Stubs.kt b/lint/lint-gradle/src/test/java/androidx/lint/gradle/Stubs.kt
index eb8807d..730d09b 100644
--- a/lint/lint-gradle/src/test/java/androidx/lint/gradle/Stubs.kt
+++ b/lint/lint-gradle/src/test/java/androidx/lint/gradle/Stubs.kt
@@ -53,6 +53,12 @@
}
interface TaskProvider<T : Task> : Provider<T>
+ @Retention
+ @Target(AnnotationTarget.FUNCTION, AnnotationTarget.FIELD)
+ annotation class Internal(
+ val value: String = ""
+ )
+
""".trimIndent()
),
kotlin(
@@ -98,5 +104,31 @@
class Closure
""".trimIndent()
+ ),
+ kotlin(
+ """
+ package org.gradle.api.component
+
+ interface SoftwareComponent
+ """.trimIndent()
+ ),
+ kotlin(
+ """
+ package org.gradle.api.internal.component
+
+ import org.gradle.api.component.SoftwareComponent
+
+ interface SoftwareComponentInternal : SoftwareComponent {
+ fun getUsages() : Set<out UsageContext>
+ }
+
+ interface UsageContext
+ """.trimIndent()
+ ),
+ kotlin(
+ """
+ package com.android.build.gradle.internal.lint
+ abstract class VariantInputs
+ """.trimIndent()
)
)
diff --git a/stableaidl/stableaidl-gradle-plugin/lint-baseline.xml b/stableaidl/stableaidl-gradle-plugin/lint-baseline.xml
new file mode 100644
index 0000000..713ffa8
--- /dev/null
+++ b/stableaidl/stableaidl-gradle-plugin/lint-baseline.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.4.0-alpha09" type="baseline" client="gradle" dependencies="false" name="AGP (8.4.0-alpha09)" variant="all" version="8.4.0-alpha09">
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Android Gradle Plugin APIs"
+ errorLine1="import com.android.build.gradle.internal.LoggerWrapper"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/java/androidx/stableaidl/internal/process/GradleProcessExecutor.kt"/>
+ </issue>
+
+ <issue
+ id="InternalGradleApiUsage"
+ message="Avoid using internal Gradle APIs"
+ errorLine1="import org.gradle.process.internal.ExecException"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/main/java/androidx/stableaidl/internal/process/GradleProcessResult.kt"/>
+ </issue>
+
+</issues>