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:
@@ -35,7 +35,6 @@ class AndroidSrcXmlDetector : ResourceXmlDetector() {
|
||||
|
||||
const val ERROR_MESSAGE = "Using android:src to define resource instead of app:srcCompat"
|
||||
|
||||
@VisibleForTesting
|
||||
val ISSUE_XML_SRC_USAGE = Issue.create(
|
||||
id = "AndroidSrcXmlDetector",
|
||||
briefDescription = "Prohibits using android:src in ImageViews and ImageButtons",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* 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
|
||||
package mozilla.components.tooling.lint
|
||||
|
||||
import com.android.SdkConstants
|
||||
import com.android.SdkConstants.ATTR_STYLE
|
||||
@@ -2,7 +2,7 @@
|
||||
* 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
|
||||
package mozilla.components.tooling.lint
|
||||
|
||||
import com.android.resources.ResourceFolderType
|
||||
import com.android.tools.lint.detector.api.Category
|
||||
@@ -2,7 +2,7 @@
|
||||
* 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
|
||||
package mozilla.components.tooling.lint
|
||||
|
||||
import com.android.tools.lint.detector.api.*
|
||||
import com.intellij.psi.PsiMethod
|
||||
@@ -2,7 +2,7 @@
|
||||
* 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
|
||||
package mozilla.components.tooling.lint
|
||||
|
||||
import com.android.tools.lint.client.api.UElementHandler
|
||||
import com.android.tools.lint.detector.api.JavaContext
|
||||
@@ -2,10 +2,17 @@
|
||||
* 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
|
||||
package mozilla.components.tooling.lint
|
||||
|
||||
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.UFile
|
||||
|
||||
@@ -22,7 +29,7 @@ class LicenseDetector : Detector(), SourceCodeScanner {
|
||||
id = "MissingLicense",
|
||||
briefDescription = "File doesn't start with the license comment",
|
||||
explanation = "Every file must start with the license comment:\n" +
|
||||
LicenseCommentChecker.ValidLicenseForKotlinFiles,
|
||||
LicenseCommentChecker.ValidLicenseForKotlinFiles,
|
||||
category = Category.CORRECTNESS,
|
||||
severity = Severity.WARNING,
|
||||
implementation = Implementation,
|
||||
@@ -15,6 +15,9 @@ import com.android.tools.lint.detector.api.Issue
|
||||
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,
|
||||
LintLogChecks.ISSUE_LOG_USAGE,
|
||||
AndroidSrcXmlDetector.ISSUE_XML_SRC_USAGE,
|
||||
TextViewAndroidSrcXmlDetector.ISSUE_XML_SRC_USAGE,
|
||||
@@ -28,7 +31,7 @@ class LintIssueRegistry : IssueRegistry() {
|
||||
StringLintXmlDetector.ISSUE_STRAIGHT_DOUBLE_QUOTE_USAGE,
|
||||
StringLintXmlDetector.ISSUE_BRAND_USAGE,
|
||||
StringLintXmlDetector.ISSUE_PLACEHOLDER_COMMENT,
|
||||
)
|
||||
) + ConstraintLayoutPerfDetector.ISSUES + ContextCompatDetector.ISSUES
|
||||
override val vendor: Vendor = Vendor(
|
||||
vendorName = "Mozilla",
|
||||
identifier = "mozilla-android-components",
|
||||
|
||||
@@ -765,7 +765,6 @@ dependencies {
|
||||
// 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}"
|
||||
|
||||
lintChecks project(":mozilla-lint-rules")
|
||||
lintChecks project(':tooling-lint')
|
||||
}
|
||||
|
||||
|
||||
@@ -32,5 +32,4 @@ fi
|
||||
assembleDebug \
|
||||
assembleDebugAndroidTest \
|
||||
mozilla-detekt-rules:test \
|
||||
mozilla-lint-rules:test \
|
||||
testDebug
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
/build
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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",
|
||||
)
|
||||
}
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -45,7 +45,6 @@ apply from: file('../autopublish-settings.gradle')
|
||||
|
||||
include ':app'
|
||||
include ':mozilla-detekt-rules'
|
||||
include ':mozilla-lint-rules'
|
||||
include ':benchmark'
|
||||
|
||||
gradle.projectsLoaded { ->
|
||||
|
||||
@@ -452,6 +452,578 @@
|
||||
column="9"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="ButtonStyleXmlDetector"
|
||||
message="All buttons must have a style, try using NeutralButton or similar."
|
||||
errorLine1=" <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=" <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=" <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=" <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=" <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'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
|
||||
id="NonConstantResourceId"
|
||||
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"/>
|
||||
</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
|
||||
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"
|
||||
@@ -617,6 +1244,28 @@
|
||||
column="30"/>
|
||||
</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=" <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=" <androidx.constraintlayout.widget.ConstraintLayout"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="src/main/res/layout/fragment_search_suggestions.xml"
|
||||
line="88"
|
||||
column="6"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
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."
|
||||
|
||||
@@ -46,7 +46,6 @@ System.setProperty('android.home', gradle.mozconfig.substs.ANDROID_SDK_ROOT)
|
||||
include ':annotations', ':messaging_example', ':port_messaging_example'
|
||||
include ':geckoview'
|
||||
include ':exoplayer2'
|
||||
include ':mozilla-lint-rules'
|
||||
include ':android-components'
|
||||
|
||||
project(':annotations').projectDir = new File("${gradle.mozconfig.topsrcdir}/mobile/android/annotations")
|
||||
|
||||
@@ -69,7 +69,7 @@ fenix:
|
||||
run:
|
||||
pre-gradlew:
|
||||
- ["cd", "mobile/android/fenix"]
|
||||
gradlew: ['lintDebug', 'mozilla-lint-rules:test']
|
||||
gradlew: ['lintDebug']
|
||||
treeherder:
|
||||
symbol: lint(fenix)
|
||||
worker:
|
||||
|
||||
@@ -60,11 +60,7 @@ def _get_upstream_deps_per_gradle_project(gradle_root, existing_build_config):
|
||||
local_dep_match = _LOCAL_DEPENDENCY_PATTERN.search(line)
|
||||
if local_dep_match:
|
||||
local_dependency_name = local_dep_match.group("local_dependency_name")
|
||||
if (
|
||||
local_dependency_name != current_project_name
|
||||
# These lint rules are not part of android-components
|
||||
and local_dependency_name != "mozilla-lint-rules"
|
||||
):
|
||||
if local_dependency_name != current_project_name:
|
||||
project_dependencies[current_project_name].add(local_dependency_name)
|
||||
|
||||
return {
|
||||
|
||||
@@ -18,7 +18,7 @@ export MOZCONFIG=mobile/android/config/mozconfigs/android-arm-gradle-dependencie
|
||||
./mach gradle downloadDependencies --no-configuration-cache
|
||||
./mach android gradle-dependencies --no-configuration-cache
|
||||
pushd mobile/android/fenix
|
||||
./gradlew detekt lint assembleDebug mozilla-lint-rules:test :benchmark:assembleBenchmark
|
||||
./gradlew detekt lint assembleDebug :benchmark:assembleBenchmark
|
||||
popd
|
||||
pushd mobile/android/focus-android
|
||||
./gradlew lint
|
||||
|
||||
Reference in New Issue
Block a user