Bug 1872229 - Move mozilla-lint-rules to tooling-lint r=tcampbell,android-reviewers,adhingra,mcarare

There are only a few more rules in the fenix project that are better
having in the tooling-lint component, so lets just move that here.

Differential Revision: https://phabricator.services.mozilla.com/D236048
This commit is contained in:
Jonathan Almeida
2025-04-11 04:37:30 +00:00
parent c979178674
commit fd7f7bef84
23 changed files with 670 additions and 741 deletions

View File

@@ -35,7 +35,6 @@ class AndroidSrcXmlDetector : ResourceXmlDetector() {
const val ERROR_MESSAGE = "Using android:src to define resource instead of app:srcCompat" const val ERROR_MESSAGE = "Using android:src to define resource instead of app:srcCompat"
@VisibleForTesting
val ISSUE_XML_SRC_USAGE = Issue.create( val ISSUE_XML_SRC_USAGE = Issue.create(
id = "AndroidSrcXmlDetector", id = "AndroidSrcXmlDetector",
briefDescription = "Prohibits using android:src in ImageViews and ImageButtons", briefDescription = "Prohibits using android:src in ImageViews and ImageButtons",

View File

@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.lintrules package mozilla.components.tooling.lint
import com.android.SdkConstants import com.android.SdkConstants
import com.android.SdkConstants.ATTR_STYLE import com.android.SdkConstants.ATTR_STYLE

View File

@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.lintrules.perf package mozilla.components.tooling.lint
import com.android.resources.ResourceFolderType import com.android.resources.ResourceFolderType
import com.android.tools.lint.detector.api.Category import com.android.tools.lint.detector.api.Category

View File

@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.lintrules package mozilla.components.tooling.lint
import com.android.tools.lint.detector.api.* import com.android.tools.lint.detector.api.*
import com.intellij.psi.PsiMethod import com.intellij.psi.PsiMethod

View File

@@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.lintrules package mozilla.components.tooling.lint
import com.android.tools.lint.client.api.UElementHandler import com.android.tools.lint.client.api.UElementHandler
import com.android.tools.lint.detector.api.JavaContext import com.android.tools.lint.detector.api.JavaContext

View File

@@ -2,10 +2,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.lintrules package mozilla.components.tooling.lint
import com.android.tools.lint.client.api.UElementHandler import com.android.tools.lint.client.api.UElementHandler
import com.android.tools.lint.detector.api.* 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.UElement
import org.jetbrains.uast.UFile import org.jetbrains.uast.UFile

View File

@@ -15,6 +15,9 @@ import com.android.tools.lint.detector.api.Issue
class LintIssueRegistry : IssueRegistry() { class LintIssueRegistry : IssueRegistry() {
override val api: Int = com.android.tools.lint.detector.api.CURRENT_API override val api: Int = com.android.tools.lint.detector.api.CURRENT_API
override val issues: List<Issue> = listOf( override val issues: List<Issue> = listOf(
ButtonStyleXmlDetector.ISSUE_XML_STYLE,
LicenseDetector.ISSUE_MISSING_LICENSE,
LicenseDetector.ISSUE_INVALID_LICENSE_FORMAT,
LintLogChecks.ISSUE_LOG_USAGE, LintLogChecks.ISSUE_LOG_USAGE,
AndroidSrcXmlDetector.ISSUE_XML_SRC_USAGE, AndroidSrcXmlDetector.ISSUE_XML_SRC_USAGE,
TextViewAndroidSrcXmlDetector.ISSUE_XML_SRC_USAGE, TextViewAndroidSrcXmlDetector.ISSUE_XML_SRC_USAGE,
@@ -28,7 +31,7 @@ class LintIssueRegistry : IssueRegistry() {
StringLintXmlDetector.ISSUE_STRAIGHT_DOUBLE_QUOTE_USAGE, StringLintXmlDetector.ISSUE_STRAIGHT_DOUBLE_QUOTE_USAGE,
StringLintXmlDetector.ISSUE_BRAND_USAGE, StringLintXmlDetector.ISSUE_BRAND_USAGE,
StringLintXmlDetector.ISSUE_PLACEHOLDER_COMMENT, StringLintXmlDetector.ISSUE_PLACEHOLDER_COMMENT,
) ) + ConstraintLayoutPerfDetector.ISSUES + ContextCompatDetector.ISSUES
override val vendor: Vendor = Vendor( override val vendor: Vendor = Vendor(
vendorName = "Mozilla", vendorName = "Mozilla",
identifier = "mozilla-android-components", identifier = "mozilla-android-components",

View File

@@ -765,7 +765,6 @@ dependencies {
// depend on a separate library for unit tests. This will be removed in future releases. // depend on a separate library for unit tests. This will be removed in future releases.
testImplementation "org.mozilla.telemetry:glean-native-forUnitTests:${project.ext.glean_version}" testImplementation "org.mozilla.telemetry:glean-native-forUnitTests:${project.ext.glean_version}"
lintChecks project(":mozilla-lint-rules")
lintChecks project(':tooling-lint') lintChecks project(':tooling-lint')
} }

View File

@@ -32,5 +32,4 @@ fi
assembleDebug \ assembleDebug \
assembleDebugAndroidTest \ assembleDebugAndroidTest \
mozilla-detekt-rules:test \ mozilla-detekt-rules:test \
mozilla-lint-rules:test \
testDebug testDebug

View File

@@ -1 +0,0 @@
/build

View File

@@ -1,80 +0,0 @@
/* 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/. */
package org.mozilla.fenix.lintrules
import com.android.SdkConstants.ATTR_SRC
import com.android.SdkConstants.FQCN_IMAGE_BUTTON
import com.android.SdkConstants.FQCN_IMAGE_VIEW
import com.android.SdkConstants.IMAGE_BUTTON
import com.android.SdkConstants.IMAGE_VIEW
import com.android.resources.ResourceFolderType
import com.android.tools.lint.detector.api.Category
import com.android.tools.lint.detector.api.Implementation
import com.android.tools.lint.detector.api.Issue
import com.android.tools.lint.detector.api.ResourceXmlDetector
import com.android.tools.lint.detector.api.Scope
import com.android.tools.lint.detector.api.Severity
import com.android.tools.lint.detector.api.XmlContext
import org.w3c.dom.Element
/**
* A custom lint check that prohibits not using the app:srcCompat for ImageViews
*/
class AndroidSrcXmlDetector : ResourceXmlDetector() {
companion object {
const val SCHEMA = "http://schemas.android.com/apk/res/android"
const val FULLY_QUALIFIED_APP_COMPAT_IMAGE_BUTTON =
"androidx.appcompat.widget.AppCompatImageButton"
const val FULLY_QUALIFIED_APP_COMPAT_VIEW_CLASS =
"androidx.appcompat.widget.AppCompatImageView"
const val APP_COMPAT_IMAGE_BUTTON = "AppCompatImageButton"
const val APP_COMPAT_IMAGE_VIEW = "AppCompatImageView"
const val ERROR_MESSAGE = "Using android:src to define resource instead of app:srcCompat"
val ISSUE_XML_SRC_USAGE = Issue.create(
id = "AndroidSrcXmlDetector",
briefDescription = "Prohibits using android:src in ImageViews and ImageButtons",
explanation = "ImageView (and descendants) images should be declared using app:srcCompat",
category = Category.CORRECTNESS,
severity = Severity.ERROR,
implementation = Implementation(
AndroidSrcXmlDetector::class.java,
Scope.RESOURCE_FILE_SCOPE,
),
)
}
override fun appliesTo(folderType: ResourceFolderType): Boolean {
// Return true if we want to analyze resource files in the specified resource
// folder type. In this case we only need to analyze layout resource files.
return folderType == ResourceFolderType.LAYOUT
}
override fun getApplicableElements(): Collection<String>? {
return setOf(
FQCN_IMAGE_VIEW,
IMAGE_VIEW,
FQCN_IMAGE_BUTTON,
IMAGE_BUTTON,
FULLY_QUALIFIED_APP_COMPAT_IMAGE_BUTTON,
FULLY_QUALIFIED_APP_COMPAT_VIEW_CLASS,
APP_COMPAT_IMAGE_BUTTON,
APP_COMPAT_IMAGE_VIEW,
)
}
override fun visitElement(context: XmlContext, element: Element) {
if (!element.hasAttributeNS(SCHEMA, ATTR_SRC)) return
val node = element.getAttributeNodeNS(SCHEMA, ATTR_SRC)
context.report(
issue = ISSUE_XML_SRC_USAGE,
scope = node,
location = context.getLocation(node),
message = ERROR_MESSAGE,
)
}
}

View File

@@ -1,81 +0,0 @@
/* 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/. */
package org.mozilla.fenix.lintrules
import com.android.SdkConstants.ATTR_TINT
import com.android.SdkConstants.FQCN_IMAGE_BUTTON
import com.android.SdkConstants.FQCN_IMAGE_VIEW
import com.android.SdkConstants.IMAGE_BUTTON
import com.android.SdkConstants.IMAGE_VIEW
import com.android.resources.ResourceFolderType
import com.android.tools.lint.detector.api.Category
import com.android.tools.lint.detector.api.Implementation
import com.android.tools.lint.detector.api.Issue
import com.android.tools.lint.detector.api.ResourceXmlDetector
import com.android.tools.lint.detector.api.Scope
import com.android.tools.lint.detector.api.Severity
import com.android.tools.lint.detector.api.XmlContext
import org.w3c.dom.Element
/**
* A custom lint check that prohibits not using the app:tint for ImageViews
*/
class ImageViewAndroidTintXmlDetector : ResourceXmlDetector() {
companion object {
const val SCHEMA = "http://schemas.android.com/apk/res/android"
const val FULLY_QUALIFIED_APP_COMPAT_IMAGE_BUTTON =
"androidx.appcompat.widget.AppCompatImageButton"
const val FULLY_QUALIFIED_APP_COMPAT_VIEW_CLASS =
"androidx.appcompat.widget.AppCompatImageView"
const val APP_COMPAT_IMAGE_BUTTON = "AppCompatImageButton"
const val APP_COMPAT_IMAGE_VIEW = "AppCompatImageView"
const val ERROR_MESSAGE =
"Using android:tint to tint ImageView instead of app:tint with AppCompatImageView"
val ISSUE_XML_SRC_USAGE = Issue.create(
id = "AndroidSrcXmlDetector",
briefDescription = "Prohibits using android:tint in ImageViews and ImageButtons",
explanation = "ImageView (and descendants) should be tinted using app:tint",
category = Category.CORRECTNESS,
severity = Severity.ERROR,
implementation = Implementation(
ImageViewAndroidTintXmlDetector::class.java,
Scope.RESOURCE_FILE_SCOPE,
),
)
}
override fun appliesTo(folderType: ResourceFolderType): Boolean {
// Return true if we want to analyze resource files in the specified resource
// folder type. In this case we only need to analyze layout resource files.
return folderType == ResourceFolderType.LAYOUT
}
override fun getApplicableElements(): Collection<String>? {
return setOf(
FQCN_IMAGE_VIEW,
IMAGE_VIEW,
FQCN_IMAGE_BUTTON,
IMAGE_BUTTON,
FULLY_QUALIFIED_APP_COMPAT_IMAGE_BUTTON,
FULLY_QUALIFIED_APP_COMPAT_VIEW_CLASS,
APP_COMPAT_IMAGE_BUTTON,
APP_COMPAT_IMAGE_VIEW,
)
}
override fun visitElement(context: XmlContext, element: Element) {
if (!element.hasAttributeNS(SCHEMA, ATTR_TINT)) return
val node = element.getAttributeNodeNS(SCHEMA, ATTR_TINT)
context.report(
issue = ISSUE_XML_SRC_USAGE,
scope = node,
location = context.getLocation(node),
message = ERROR_MESSAGE,
)
}
}

View File

@@ -1,27 +0,0 @@
/* 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/. */
package org.mozilla.fenix.lintrules
import com.android.tools.lint.client.api.IssueRegistry
import com.android.tools.lint.client.api.Vendor
import com.android.tools.lint.detector.api.Issue
import org.mozilla.fenix.lintrules.perf.ConstraintLayoutPerfDetector
/**
* Registry which provides a list of our custom lint checks to be performed on an Android project.
*/
@Suppress("unused")
class LintIssueRegistry : IssueRegistry() {
override val api: Int = com.android.tools.lint.detector.api.CURRENT_API
override val issues: List<Issue> = listOf(
ButtonStyleXmlDetector.ISSUE_XML_STYLE,
LicenseDetector.ISSUE_MISSING_LICENSE,
LicenseDetector.ISSUE_INVALID_LICENSE_FORMAT,
) + ConstraintLayoutPerfDetector.ISSUES + ContextCompatDetector.ISSUES
override val vendor: Vendor = Vendor(
vendorName = "Mozilla",
identifier = "mozilla-fenix",
)
}

View File

@@ -1,97 +0,0 @@
/* 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/. */
package org.mozilla.fenix.lintrules
import com.android.SdkConstants.ATTR_DRAWABLE_BOTTOM
import com.android.SdkConstants.ATTR_DRAWABLE_END
import com.android.SdkConstants.ATTR_DRAWABLE_LEFT
import com.android.SdkConstants.ATTR_DRAWABLE_RIGHT
import com.android.SdkConstants.ATTR_DRAWABLE_START
import com.android.SdkConstants.ATTR_DRAWABLE_TOP
import com.android.SdkConstants.FQCN_TEXT_VIEW
import com.android.SdkConstants.TEXT_VIEW
import com.android.resources.ResourceFolderType
import com.android.tools.lint.detector.api.Category
import com.android.tools.lint.detector.api.Implementation
import com.android.tools.lint.detector.api.Issue
import com.android.tools.lint.detector.api.ResourceXmlDetector
import com.android.tools.lint.detector.api.Scope
import com.android.tools.lint.detector.api.Severity
import com.android.tools.lint.detector.api.XmlContext
import org.w3c.dom.Element
/**
* A custom lint check that prohibits not using the app:drawableXCompat to define drawables in TextViews
*/
class TextViewAndroidSrcXmlDetector : ResourceXmlDetector() {
companion object {
const val SCHEMA = "http://schemas.android.com/apk/res/android"
const val ERROR_MESSAGE =
"Using android:drawableX to define resource instead of app:drawableXCompat"
val ISSUE_XML_SRC_USAGE = Issue.create(
id = "TextViewAndroidSrcXmlDetector",
briefDescription = "Prohibits using android namespace to define drawables in TextViews",
explanation = "TextView drawables should be declared using app:drawableXCompat",
category = Category.CORRECTNESS,
severity = Severity.ERROR,
implementation = Implementation(
TextViewAndroidSrcXmlDetector::class.java,
Scope.RESOURCE_FILE_SCOPE,
),
)
}
override fun appliesTo(folderType: ResourceFolderType): Boolean {
// Return true if we want to analyze resource files in the specified resource
// folder type. In this case we only need to analyze layout resource files.
return folderType == ResourceFolderType.LAYOUT
}
override fun getApplicableElements(): Collection<String>? {
return setOf(
FQCN_TEXT_VIEW,
TEXT_VIEW,
)
}
override fun visitElement(context: XmlContext, element: Element) {
val node = when {
element.hasAttributeNS(SCHEMA, ATTR_DRAWABLE_BOTTOM) -> element.getAttributeNodeNS(
SCHEMA,
ATTR_DRAWABLE_BOTTOM,
)
element.hasAttributeNS(SCHEMA, ATTR_DRAWABLE_END) -> element.getAttributeNodeNS(
SCHEMA,
ATTR_DRAWABLE_END,
)
element.hasAttributeNS(SCHEMA, ATTR_DRAWABLE_LEFT) -> element.getAttributeNodeNS(
SCHEMA,
ATTR_DRAWABLE_LEFT,
)
element.hasAttributeNS(
SCHEMA,
ATTR_DRAWABLE_RIGHT,
) -> element.getAttributeNodeNS(SCHEMA, ATTR_DRAWABLE_RIGHT)
element.hasAttributeNS(
SCHEMA,
ATTR_DRAWABLE_START,
) -> element.getAttributeNodeNS(SCHEMA, ATTR_DRAWABLE_START)
element.hasAttributeNS(SCHEMA, ATTR_DRAWABLE_TOP) -> element.getAttributeNodeNS(
SCHEMA,
ATTR_DRAWABLE_TOP,
)
else -> null
} ?: return
context.report(
issue = ISSUE_XML_SRC_USAGE,
scope = node,
location = context.getLocation(node),
message = ERROR_MESSAGE,
)
}
}

View File

@@ -1,163 +0,0 @@
/* 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/. */
package org.mozilla.fenix.lintrules
import com.android.tools.lint.checks.infrastructure.LintDetectorTest
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
@RunWith(JUnit4::class)
class ContextCompatDetectorTest : LintDetectorTest() {
override fun getDetector(): Detector = ContextCompatDetector()
override fun getIssues(): MutableList<Issue> = ContextCompatDetector.ISSUES.toMutableList()
@Test
fun `report error when the ContextCompat getDrawable method is called`() {
val code = """
|package example
|
|import androidx.core.content.ContextCompat
|import android.content.Context
|
|class Fake {
|
| fun trigger(context: Context, id: Int) {
| ContextCompat.getDrawable(context, id)
| }
|
|}""".trimMargin()
val expectedReport = """
|src/example/Fake.kt:9: Error: This call can lead to crashes, replace with AppCompatResources.getDrawable [UnsafeCompatGetDrawable]
| ContextCompat.getDrawable(context, id)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|1 errors, 0 warnings""".trimMargin()
val expectedFixOutput = """
|Fix for src/example/Fake.kt line 9: Replace with AppCompatResources.getDrawable:
|@@ -9 +9
|- ContextCompat.getDrawable(context, id)
|+ AppCompatResources.getDrawable(context, id)""".trimMargin()
lint()
.files(Context, ContextCompat, kotlin(code))
.allowMissingSdk(true)
.run()
.expect(expectedReport)
.expectFixDiffs(expectedFixOutput)
}
@Test
fun `report error when the ContextCompat getColorStateList method is called`() {
val code = """
|package example
|
|import androidx.core.content.ContextCompat
|import android.content.Context
|
|class Fake {
|
| fun trigger(context: Context, id: Int) {
| ContextCompat.getColorStateList(context, id)
| }
|
|}""".trimMargin()
val expectedReport = """
|src/example/Fake.kt:9: Error: This call can lead to crashes, replace with AppCompatResources.getColorStateList [UnsafeCompatGetColorStateList]
| ContextCompat.getColorStateList(context, id)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|1 errors, 0 warnings""".trimMargin()
val expectedFixOutput = """
|Fix for src/example/Fake.kt line 9: Replace with AppCompatResources.getColorStateList:
|@@ -9 +9
|- ContextCompat.getColorStateList(context, id)
|+ AppCompatResources.getColorStateList(context, id)""".trimMargin()
lint()
.files(Context, ContextCompat, kotlin(code))
.allowMissingSdk(true)
.run()
.expect(expectedReport)
.expectFixDiffs(expectedFixOutput)
}
@Test
fun `does not report any errors if the getDrawable method being called is not from the ContextCompat class`() {
val code = """
|package example
|
|import android.content.Context
|
|class Fake {
|
| fun trigger(context: Context, id: Int) {
| getDrawable(context, id)
| }
|
| fun getDrawable(context: Context, id: Int) {}
|
|}""".trimMargin()
lint()
.files(Context, kotlin(code))
.allowMissingSdk(true)
.run()
.expectClean()
}
@Test
fun `does not report any errors if the getColorStateList method being called is not from the ContextCompat class`() {
val code = """
|package example
|
|import android.content.Context
|
|class Fake {
|
| fun trigger(context: Context, id: Int) {
| getColorStateList(context, id)
| }
|
| fun getColorStateList(context: Context, id: Int) {}
|
|}""".trimMargin()
lint()
.files(Context, kotlin(code))
.allowMissingSdk(true)
.run()
.expectClean()
}
// As Lint doesn't have access to the real corresponding classes, we have to provide stubs
companion object Stubs {
private val Context = java(
"""
|package android.content;
|
|public class Context {}
|""".trimMargin()
)
private val ContextCompat = java(
"""
|package androidx.core.content;
|
|public class ContextCompat {
| public static void getDrawable(Context context, int resId) {}
| public static void getColorStateList(Context context, int resId) {}
|}
|""".trimMargin()
)
}
}

View File

@@ -1,155 +0,0 @@
/* 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/. */
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.checks.infrastructure.TestMode
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.LicenseCommentChecker.Companion.ValidLicenseForKotlinFiles
import org.mozilla.fenix.lintrules.LicenseDetector.Companion.ISSUE_INVALID_LICENSE_FORMAT
import org.mozilla.fenix.lintrules.LicenseDetector.Companion.ISSUE_MISSING_LICENSE
@RunWith(JUnit4::class)
class LicenseDetectorTest : LintDetectorTest() {
override fun getIssues(): MutableList<Issue> =
mutableListOf(ISSUE_MISSING_LICENSE, ISSUE_INVALID_LICENSE_FORMAT)
override fun getDetector(): Detector = LicenseDetector()
@Test
fun `report missing license if it isn't at the top of the file`() {
val code = """
|package example
|
|class SomeExample {
| fun test() {
| val x = 10
| println("Hello")
| }
|}""".trimMargin()
val expectedReport = """
|src/example/SomeExample.kt:1: Warning: The file must start with a comment containing the license [MissingLicense]
|package example
|~~~~~~~~~~~~~~~
|0 errors, 1 warnings""".trimMargin()
val expectedFixOutput = """
|Fix for src/example/SomeExample.kt line 1: Insert license at the top of the file:
|@@ -1 +1
|+ /* 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/. */
|+""".trimMargin()
lint()
.files(TestFiles.kt(code))
.allowMissingSdk(true)
.testModes(TestMode.DEFAULT)
.run()
.expect(expectedReport)
.expectFixDiffs(expectedFixOutput)
}
@Test
fun `report invalid license format if it doesn't have a leading newline character`() {
val code = """
|$ValidLicenseForKotlinFiles
|package example
|
|class SomeExample {
| fun test() {
| val x = 10
| println("Hello")
| }
|}""".trimMargin()
val expectedReport = """
|src/example/SomeExample.kt:3: Warning: The license comment must be followed by a newline character [InvalidLicenseFormat]
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
| ~
|0 errors, 1 warnings""".trimMargin()
val expectedFixOutput = """
|Fix for src/example/SomeExample.kt line 3: Insert newline character after the license:
|@@ -4 +4
|+""".trimMargin()
lint()
.files(TestFiles.kt(code))
.allowMissingSdk(true)
.testModes(TestMode.DEFAULT)
.run()
.expect(expectedReport)
.expectFixDiffs(expectedFixOutput)
}
@Test
fun `valid license does not generate a warning`() {
val code = """
|$ValidLicenseForKotlinFiles
|
|package example
|
|class SomeExample {
| fun test() {
| val x = 10
| println("Hello")
| }
|}""".trimMargin()
lint()
.files(TestFiles.kt(code))
.allowMissingSdk(true)
.testModes(TestMode.DEFAULT)
.run()
.expectClean()
}
@Test
fun `report incorrectly formatted license`() {
val code = """
|/* 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/. */
|
|package example
|
|class SomeExample {
| fun test() {
| val x = 10
| println("Hello")
| }
|}""".trimMargin()
val expectedReport = """
|src/example/SomeExample.kt:1: Warning: The license comment doesn't have the appropriate format [InvalidLicenseFormat]
|/* This Source Code Form is subject to the terms of the Mozilla Public
|^
|0 errors, 1 warnings""".trimMargin()
val expectedFixOutput = """
|Fix for src/example/SomeExample.kt line 1: Replace with correctly formatted license:
|@@ -2 +2
|- 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/. */
|+ * 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/. */""".trimMargin()
lint()
.files(TestFiles.kt(code))
.allowMissingSdk(true)
.testModes(TestMode.DEFAULT)
.run()
.expect(expectedReport)
.expectFixDiffs(expectedFixOutput)
}
}

View File

@@ -1,117 +0,0 @@
/* 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/. */
package org.mozilla.fenix.lintrules.perf
import com.android.resources.ResourceFolderType
import com.android.tools.lint.checks.infrastructure.TestFiles
import com.android.tools.lint.checks.infrastructure.TestLintTask.lint
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Ignore
import org.junit.Test
// FQCN = fully qualified class name
private const val FQCN_CONSTRAINT_LAYOUT = "androidx.constraintlayout.widget.ConstraintLayout"
private const val FQCN_CUSTOM_VIEW = "org.mozilla.fenix.library.LibrarySiteItemView" // chosen arbitrarily
private val ALL_ISSUES = ConstraintLayoutPerfDetector.ISSUES.toTypedArray()
class ConstraintLayoutPerfDetectorTest {
private lateinit var detector: ConstraintLayoutPerfDetector
@Before
fun setUp() {
detector = ConstraintLayoutPerfDetector()
}
@Test
fun `WHEN checking file types THEN it only applies layout`() {
val excludedType = ResourceFolderType.LAYOUT
val allTypeButLayout = ResourceFolderType.entries.filter { it != excludedType }
allTypeButLayout.forEach { assertFalse(detector.appliesTo(it)) }
assertTrue(detector.appliesTo(excludedType))
}
@Test
fun `WHEN checking applicable elements THEN it applies to ConstraintLayout` () {
assertTrue(detector.getApplicableElements()!!.contains(
"androidx.constraintlayout.widget.ConstraintLayout"
))
}
@Test
fun `WHEN checking applicable elements THEN it doesnt apply to some common ones`() {
val applicableElements = detector.getApplicableElements()!!
listOf(
"LinearLayout",
"fragment"
).forEach { assertFalse(it, applicableElements.contains(it)) }
}
@Test
fun `GIVEN a file with one ConstraintLayout WHEN detecting THEN pass`() {
val layout = getLayoutWithConstraintLayoutRoot("<TextView/>")
lint()
.files(getTestXml(layout))
.issues(*ALL_ISSUES)
.run()
.expectClean()
}
@Test
fun `GIVEN a file with two ConstraintLayouts WHEN detecting THEN fail`() {
// Since we're not the root view, we need to indent extra.
val innerLayout = """<$FQCN_CONSTRAINT_LAYOUT
| android:layout_width="match_parent"
| android:layout_height="match_parent">
|
| </$FQCN_CONSTRAINT_LAYOUT>
""".trimMargin()
val layout = getLayoutWithConstraintLayoutRoot(innerLayout)
lint()
.files(getTestXml(layout))
.issues(*ALL_ISSUES)
.run()
.expectWarningCount(0)
.expectErrorCount(1)
}
@Ignore("the lint test API seems to be broken: project0: Error: Unexpected failure during " +
"lint analysis (this is a bug in lint or one of the libraries it depends on). Message: The " +
"prefix \"android\" for attribute \"android:layout_width\" associated with an element type \"TextView\" is not bound.")
@Test
fun `GIVEN a file with a ConstraintLayout and a custom view ConstraintLayout layout WHEN detecting THEN warning`() {
val innerLayout = """<TextView
| android:layout_width="match_parent"
| android:layout_height="match_parent">
|
| </$FQCN_CUSTOM_VIEW>
""".trimMargin()
lint()
.files(getTestXml(innerLayout))
.issues(*ALL_ISSUES)
.run()
.expectWarningCount(1)
.expectErrorCount(0)
}
private fun getTestXml(code: String) = TestFiles.xml("res/layout/activity_home.xml", code)
private fun getLayoutWithConstraintLayoutRoot(innerLayout: String = "") = """<!-- 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/. -->
| <$FQCN_CONSTRAINT_LAYOUT
| xmlns:android="http://schemas.android.com/apk/res/android"
| android:layout_width="match_parent"
| android:layout_height="match_parent">
|
| $innerLayout
|
| </$FQCN_CONSTRAINT_LAYOUT>""".trimMargin()
}

View File

@@ -45,7 +45,6 @@ apply from: file('../autopublish-settings.gradle')
include ':app' include ':app'
include ':mozilla-detekt-rules' include ':mozilla-detekt-rules'
include ':mozilla-lint-rules'
include ':benchmark' include ':benchmark'
gradle.projectsLoaded { -> gradle.projectsLoaded { ->

View File

@@ -452,6 +452,578 @@
column="9"/> column="9"/>
</issue> </issue>
<issue
id="ButtonStyleXmlDetector"
message="All buttons must have a style, try using NeutralButton or similar."
errorLine1=" &lt;Button"
errorLine2=" ~~~~~~">
<location
file="src/main/res/layout/firstrun_page.xml"
line="84"
column="14"/>
</issue>
<issue
id="ButtonStyleXmlDetector"
message="All buttons must have a style, try using NeutralButton or similar."
errorLine1=" &lt;Button"
errorLine2=" ~~~~~~">
<location
file="src/main/res/layout/fragment_crash_reporter.xml"
line="70"
column="6"/>
</issue>
<issue
id="ButtonStyleXmlDetector"
message="All buttons must have a style, try using NeutralButton or similar."
errorLine1=" &lt;Button"
errorLine2=" ~~~~~~">
<location
file="src/main/res/layout/fragment_exceptions_domains.xml"
line="30"
column="6"/>
</issue>
<issue
id="ButtonStyleXmlDetector"
message="All buttons must have a style, try using NeutralButton or similar."
errorLine1=" &lt;Button"
errorLine2=" ~~~~~~">
<location
file="src/main/res/layout/fragment_firstrun.xml"
line="13"
column="6"/>
</issue>
<issue
id="ButtonStyleXmlDetector"
message="All buttons must have a style, try using NeutralButton or similar."
errorLine1=" &lt;Button"
errorLine2=" ~~~~~~">
<location
file="src/main/res/layout/fragment_search_suggestions.xml"
line="107"
column="10"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/widget/AboutPreference.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment doesn&apos;t have the appropriate format"
errorLine1="/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-"
errorLine2="^">
<location
file="src/debug/java/org/mozilla/focus/utils/AdjustHelper.java"
line="1"
column="1"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/open/AppAdapter.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/open/AppViewHolder.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/cfr/CfrMiddleware.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/settings/privacy/ConnectionDetailsPanel.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/cookiebanner/CookieBannerFragment.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/cookiebanner/CookieBannerOption.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/cookiebanner/CookieBannerRejectAllPreference.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/ui/menu/CustomDropdownMenu.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/menu/browser/CustomTabMenu.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/activity/EraseShortcutActivity.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/ui/theme/FocusDimensions.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/settings/permissions/permissionoptions/HardwarePermissionCheckFeature.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/utils/HtmlLoader.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/open/InstallBannerViewHolder.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/locale/LocaleManager.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/locale/Locales.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/browser/LocalizedContent.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/widget/MozillaPreference.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/widget/ResizableKeyboardCoordinatorLayout.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/widget/ResizableKeyboardLinearLayout.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/widget/ResizableKeyboardViewDelegate.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/settings/SafeBrowsingSwitchPreference.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/searchsuggestions/ui/SearchOverlay.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/settings/permissions/permissionoptions/SitePermission.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/settings/permissions/SitePermissionOption.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/settings/permissions/permissionoptions/SitePermissionOptionListItem.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/settings/permissions/permissionoptions/SitePermissionOptionsFragment.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/settings/permissions/permissionoptions/SitePermissionOptionsFragmentCompose.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/settings/permissions/permissionoptions/SitePermissionOptionsScreenStore.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/settings/permissions/permissionoptions/SitePermissionOptionsStorage.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/settings/permissions/permissionoptions/SitePermissionOptionsStorageMiddleware.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/settings/permissions/SitePermissionsFragment.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/settings/privacy/studies/StudiesAdapter.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/settings/privacy/studies/StudiesFragment.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/settings/privacy/studies/StudiesListItem.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/settings/privacy/studies/StudiesRecyclerView.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/settings/privacy/studies/StudiesViewHolder.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/settings/privacy/studies/StudiesViewModel.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/session/ui/TabsPopup.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/menu/ToolbarMenu.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/topsites/TopSitesOverlay.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/settings/privacy/TrackingProtectionPanel.kt"
line="3"
column="62"/>
</issue>
<issue
id="InvalidLicenseFormat"
message="The license comment must be followed by a newline character"
errorLine1=" * file, You can obtain one at http://mozilla.org/MPL/2.0/. */"
errorLine2=" ~">
<location
file="src/main/java/org/mozilla/focus/session/VisibilityLifeCycleCallback.kt"
line="3"
column="62"/>
</issue>
<issue
id="MissingLicense"
message="The file must start with a comment containing the license"
errorLine1=""
errorLine2="^">
<location
file="src/main/java/org/mozilla/focus/widget/LocaleListPreference.java"
line="1"
column="1"/>
</issue>
<issue
id="MissingLicense"
message="The file must start with a comment containing the license"
errorLine1="package org.mozilla.focus.generated"
errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/java/org/mozilla/focus/generated/LocalesList.kt"
line="1"
column="1"/>
</issue>
<issue <issue
id="NonConstantResourceId" id="NonConstantResourceId"
message="Resource IDs will be non-final by default in Android Gradle Plugin version 8.0, avoid using them in const fields" message="Resource IDs will be non-final by default in Android Gradle Plugin version 8.0, avoid using them in const fields"
@@ -518,6 +1090,61 @@
column="13"/> column="13"/>
</issue> </issue>
<issue
id="UnsafeCompatGetDrawable"
message="This call can lead to crashes, replace with AppCompatResources.getDrawable"
errorLine1=" primaryImage = ContextCompat.getDrawable(context, R.drawable.mozac_ic_back_24)!!,"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/java/org/mozilla/focus/browser/integration/NavigationButtonsIntegration.kt"
line="48"
column="28"/>
</issue>
<issue
id="UnsafeCompatGetDrawable"
message="This call can lead to crashes, replace with AppCompatResources.getDrawable"
errorLine1=" primaryImage = ContextCompat.getDrawable(context, R.drawable.mozac_ic_forward_24)!!,"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/java/org/mozilla/focus/browser/integration/NavigationButtonsIntegration.kt"
line="65"
column="28"/>
</issue>
<issue
id="UnsafeCompatGetDrawable"
message="This call can lead to crashes, replace with AppCompatResources.getDrawable"
errorLine1=" primaryImage = ContextCompat.getDrawable(context, R.drawable.mozac_ic_stop)!!,"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/java/org/mozilla/focus/browser/integration/NavigationButtonsIntegration.kt"
line="82"
column="28"/>
</issue>
<issue
id="UnsafeCompatGetDrawable"
message="This call can lead to crashes, replace with AppCompatResources.getDrawable"
errorLine1=" secondaryImage = ContextCompat.getDrawable(context, R.drawable.mozac_ic_arrow_clockwise_24)!!,"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/java/org/mozilla/focus/browser/integration/NavigationButtonsIntegration.kt"
line="83"
column="30"/>
</issue>
<issue
id="UnsafeCompatGetDrawable"
message="This call can lead to crashes, replace with AppCompatResources.getDrawable"
errorLine1=" ContextCompat.getDrawable(binding.root.context, R.drawable.ic_link)?.intrinsicWidth ?: 0"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/java/org/mozilla/focus/session/ui/TabViewHolder.kt"
line="100"
column="13"/>
</issue>
<issue <issue
id="VectorRaster" id="VectorRaster"
message="Limit vector icons sizes to 200×200 to keep icon drawing fast; see https://developer.android.com/studio/write/vector-asset-studio#when for more" message="Limit vector icons sizes to 200×200 to keep icon drawing fast; see https://developer.android.com/studio/write/vector-asset-studio#when for more"
@@ -617,6 +1244,28 @@
column="30"/> column="30"/>
</issue> </issue>
<issue
id="MozMultipleConstraintLayouts"
message="Flatten the view hierarchy by using one `ConstraintLayout`, if possible. If the alternative is several nested `ViewGroup`, it may not help performance and this may be worth suppressing."
errorLine1=" &lt;androidx.constraintlayout.widget.ConstraintLayout"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/layout/dialog_add_to_homescreen2.xml"
line="73"
column="6"/>
</issue>
<issue
id="MozMultipleConstraintLayouts"
message="Flatten the view hierarchy by using one `ConstraintLayout`, if possible. If the alternative is several nested `ViewGroup`, it may not help performance and this may be worth suppressing."
errorLine1=" &lt;androidx.constraintlayout.widget.ConstraintLayout"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/layout/fragment_search_suggestions.xml"
line="88"
column="6"/>
</issue>
<issue <issue
id="NotifyDataSetChanged" id="NotifyDataSetChanged"
message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort." message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."

View File

@@ -46,7 +46,6 @@ System.setProperty('android.home', gradle.mozconfig.substs.ANDROID_SDK_ROOT)
include ':annotations', ':messaging_example', ':port_messaging_example' include ':annotations', ':messaging_example', ':port_messaging_example'
include ':geckoview' include ':geckoview'
include ':exoplayer2' include ':exoplayer2'
include ':mozilla-lint-rules'
include ':android-components' include ':android-components'
project(':annotations').projectDir = new File("${gradle.mozconfig.topsrcdir}/mobile/android/annotations") project(':annotations').projectDir = new File("${gradle.mozconfig.topsrcdir}/mobile/android/annotations")

View File

@@ -69,7 +69,7 @@ fenix:
run: run:
pre-gradlew: pre-gradlew:
- ["cd", "mobile/android/fenix"] - ["cd", "mobile/android/fenix"]
gradlew: ['lintDebug', 'mozilla-lint-rules:test'] gradlew: ['lintDebug']
treeherder: treeherder:
symbol: lint(fenix) symbol: lint(fenix)
worker: worker:

View File

@@ -60,11 +60,7 @@ def _get_upstream_deps_per_gradle_project(gradle_root, existing_build_config):
local_dep_match = _LOCAL_DEPENDENCY_PATTERN.search(line) local_dep_match = _LOCAL_DEPENDENCY_PATTERN.search(line)
if local_dep_match: if local_dep_match:
local_dependency_name = local_dep_match.group("local_dependency_name") local_dependency_name = local_dep_match.group("local_dependency_name")
if ( if local_dependency_name != current_project_name:
local_dependency_name != current_project_name
# These lint rules are not part of android-components
and local_dependency_name != "mozilla-lint-rules"
):
project_dependencies[current_project_name].add(local_dependency_name) project_dependencies[current_project_name].add(local_dependency_name)
return { return {

View File

@@ -18,7 +18,7 @@ export MOZCONFIG=mobile/android/config/mozconfigs/android-arm-gradle-dependencie
./mach gradle downloadDependencies --no-configuration-cache ./mach gradle downloadDependencies --no-configuration-cache
./mach android gradle-dependencies --no-configuration-cache ./mach android gradle-dependencies --no-configuration-cache
pushd mobile/android/fenix pushd mobile/android/fenix
./gradlew detekt lint assembleDebug mozilla-lint-rules:test :benchmark:assembleBenchmark ./gradlew detekt lint assembleDebug :benchmark:assembleBenchmark
popd popd
pushd mobile/android/focus-android pushd mobile/android/focus-android
./gradlew lint ./gradlew lint