From 0bc64e8ca821e2792a8efd1f017553c5355dfca4 Mon Sep 17 00:00:00 2001 From: Mugurell Date: Fri, 6 Aug 2021 10:41:22 +0300 Subject: [PATCH] For #17917 - Add a Kotlin synthetics Lint detector This would help ease the current refactoring effort by ensuring no new synthetics usages. --- app/lint-baseline.xml | 1254 +++++++++++++++++ .../lintrules/KotlinSyntheticsDetector.kt | 62 + .../fenix/lintrules/LintIssueRegistry.kt | 3 +- .../lintrules/KotlinSyntheticsDetectorTest.kt | 71 + 4 files changed, 1389 insertions(+), 1 deletion(-) create mode 100644 mozilla-lint-rules/src/main/java/org/mozilla/fenix/lintrules/KotlinSyntheticsDetector.kt create mode 100644 mozilla-lint-rules/src/test/java/org/mozilla/fenix/lintrules/KotlinSyntheticsDetectorTest.kt diff --git a/app/lint-baseline.xml b/app/lint-baseline.xml index b67d66f8f..c357cc063 100644 --- a/app/lint-baseline.xml +++ b/app/lint-baseline.xml @@ -61936,4 +61936,1258 @@ column="21"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mozilla-lint-rules/src/main/java/org/mozilla/fenix/lintrules/KotlinSyntheticsDetector.kt b/mozilla-lint-rules/src/main/java/org/mozilla/fenix/lintrules/KotlinSyntheticsDetector.kt new file mode 100644 index 000000000..92c5b8890 --- /dev/null +++ b/mozilla-lint-rules/src/main/java/org/mozilla/fenix/lintrules/KotlinSyntheticsDetector.kt @@ -0,0 +1,62 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +@file:Suppress("UnstableApiUsage") + +package org.mozilla.fenix.lintrules + +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.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.android.tools.lint.detector.api.SourceCodeScanner +import org.jetbrains.uast.UElement +import org.jetbrains.uast.UImportStatement + +/** + * Custom Lint detector that checks for deprecated "kotlinx.android.synthetic" imports. + */ +class KotlinSyntheticsDetector : Detector(), SourceCodeScanner { + + override fun createUastHandler(context: JavaContext) = object : UElementHandler() { + override fun visitImportStatement(node: UImportStatement) { + node.importReference?.asSourceString()?.let { import -> + if (import.startsWith(SYNTHETIC_IMPORT_PATTERN)) { + context.report( + DEPRECATED_KOTLIN_SYNTHETICS_ISSUE, + node, + context.getLocation(node), + DEPRECATED_KOTLIN_SYNTHETICS_MESSAGE + ) + } + } + } + } + + override fun getApplicableUastTypes(): List> { + return listOf(UImportStatement::class.java) + } + + companion object { + private const val DEPRECATED_KOTLIN_SYNTHETICS_MESSAGE = "Kotlin synthetics are to be replaced with Jetpack View Binding. " + + "Please refer to https://github.com/mozilla-mobile/fenix/issues/17917 for more details." + private const val SYNTHETIC_IMPORT_PATTERN = "kotlinx.android.synthetic" + + val DEPRECATED_KOTLIN_SYNTHETICS_ISSUE = Issue.create( + "KotlinSyntheticsDeprecation", + briefDescription = "Kotlin synthetics are deprecated and actively refactored out", + explanation = "The 'kotlin-android-extensions' Gradle plugin is deprecated and " + + "will be removed in a future Kotlin release in (or after) September 2021. " + + "We are to migrate to Jetpack View Binding. " + + "Please refer to https://github.com/mozilla-mobile/fenix/issues/17917", + category = Category.PRODUCTIVITY, + severity = Severity.ERROR, + implementation = Implementation(KotlinSyntheticsDetector::class.java, Scope.JAVA_FILE_SCOPE) + ) + } +} diff --git a/mozilla-lint-rules/src/main/java/org/mozilla/fenix/lintrules/LintIssueRegistry.kt b/mozilla-lint-rules/src/main/java/org/mozilla/fenix/lintrules/LintIssueRegistry.kt index a659a8fd0..ed6d3e208 100644 --- a/mozilla-lint-rules/src/main/java/org/mozilla/fenix/lintrules/LintIssueRegistry.kt +++ b/mozilla-lint-rules/src/main/java/org/mozilla/fenix/lintrules/LintIssueRegistry.kt @@ -21,7 +21,8 @@ class LintIssueRegistry : IssueRegistry() { TextViewAndroidSrcXmlDetector.ISSUE_XML_SRC_USAGE, ImageViewAndroidTintXmlDetector.ISSUE_XML_SRC_USAGE, LicenseDetector.ISSUE_MISSING_LICENSE, - LicenseDetector.ISSUE_INVALID_LICENSE_FORMAT + LicenseDetector.ISSUE_INVALID_LICENSE_FORMAT, + KotlinSyntheticsDetector.DEPRECATED_KOTLIN_SYNTHETICS_ISSUE ) + ConstraintLayoutPerfDetector.ISSUES + ContextCompatDetector.ISSUES override val vendor: Vendor = Vendor( vendorName = "Mozilla", diff --git a/mozilla-lint-rules/src/test/java/org/mozilla/fenix/lintrules/KotlinSyntheticsDetectorTest.kt b/mozilla-lint-rules/src/test/java/org/mozilla/fenix/lintrules/KotlinSyntheticsDetectorTest.kt new file mode 100644 index 000000000..6e94ee04e --- /dev/null +++ b/mozilla-lint-rules/src/test/java/org/mozilla/fenix/lintrules/KotlinSyntheticsDetectorTest.kt @@ -0,0 +1,71 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +@file:Suppress("UnstableApiUsage") + +package org.mozilla.fenix.lintrules + +import com.android.tools.lint.checks.infrastructure.LintDetectorTest +import com.android.tools.lint.checks.infrastructure.TestFiles +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Issue +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.mozilla.fenix.lintrules.KotlinSyntheticsDetector.Companion.DEPRECATED_KOTLIN_SYNTHETICS_ISSUE + +@RunWith(JUnit4::class) +class KotlinSyntheticsDetectorTest : LintDetectorTest() { + + override fun getIssues(): MutableList = mutableListOf(DEPRECATED_KOTLIN_SYNTHETICS_ISSUE) + + override fun getDetector(): Detector = KotlinSyntheticsDetector() + + @Test + fun `GIVEN no kotlin synthetics import WHEN KotlinSyntheticsDetector runs THEN there are no errors or exceptions`() { + val code = """ + |package example + | + |import org.mozilla.fenix.databinding.OnboardingTrackingProtectionBinding + | + |class SomeExample { + | fun hello() { + | println("World") + | } + |}""".trimMargin() + + lint() + .files(TestFiles.kt(code)) + .allowCompilationErrors() + .allowMissingSdk(true) + .run() + .expectClean() + } + + @Test + fun `GIVEN a kotlin synthetics import WHEN KotlinSyntheticsDetector runs THEN there are no errors or exceptions`() { + val code = """ + |package example + | + |import kotlinx.android.synthetic.main.layout + | + |class SomeExample { + | fun hello() { + | println("World") + | } + |}""".trimMargin() + + val expectedReport = """ + |src/example/SomeExample.kt:3: Error: Kotlin synthetics are to be replaced with Jetpack View Binding. Please refer to https://github.com/mozilla-mobile/fenix/issues/17917 for more details. [KotlinSyntheticsDeprecation] + |import kotlinx.android.synthetic.main.layout + |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + |1 errors, 0 warnings""".trimMargin() + + lint() + .files(TestFiles.kt(code)) + .allowMissingSdk(true) + .run() + .expect(expectedReport) + } +}