Lint detector for ColorStateLists that use app:alpha without android:alpha
Detection + quick fix + a new module for showing all available
AppCompat Lint rules
Bug: 146350188
Test: ./gradlew :lint-demos:lint-demo-appcompat:lint
Change-Id: I5def996beebe4d9f054044957eb4aaf1f7eb489e
diff --git a/appcompat/appcompat-lint/build.gradle b/appcompat/appcompat-lint/build.gradle
index e3e6bb0..d67f346 100644
--- a/appcompat/appcompat-lint/build.gradle
+++ b/appcompat/appcompat-lint/build.gradle
@@ -45,5 +45,5 @@
mavenVersion = LibraryVersions.APPCOMPAT
mavenGroup = LibraryGroups.APPCOMPAT
inceptionYear = "2019"
- description = "Appcompat Lint Checks"
+ description = "AppCompat Lint Checks"
}
\ No newline at end of file
diff --git a/appcompat/appcompat-lint/src/main/java/androidx/appcompat/AppCompatIssueRegistry.kt b/appcompat/appcompat-lint/src/main/java/androidx/appcompat/AppCompatIssueRegistry.kt
index 0eb6076..db273d4 100644
--- a/appcompat/appcompat-lint/src/main/java/androidx/appcompat/AppCompatIssueRegistry.kt
+++ b/appcompat/appcompat-lint/src/main/java/androidx/appcompat/AppCompatIssueRegistry.kt
@@ -16,12 +16,13 @@
package androidx.appcompat
+import androidx.appcompat.res.ColorStateListAlphaDetector
import com.android.tools.lint.client.api.IssueRegistry
import com.android.tools.lint.detector.api.CURRENT_API
class AppCompatIssueRegistry : IssueRegistry() {
override val api = CURRENT_API
override val issues get() = listOf(
- VanillaCheck.ISSUE
+ ColorStateListAlphaDetector.NOT_USING_ANDROID_ALPHA
)
}
diff --git a/appcompat/appcompat-lint/src/main/java/androidx/appcompat/VanillaCheck.kt b/appcompat/appcompat-lint/src/main/java/androidx/appcompat/VanillaCheck.kt
index 79575c2..2d35f41 100644
--- a/appcompat/appcompat-lint/src/main/java/androidx/appcompat/VanillaCheck.kt
+++ b/appcompat/appcompat-lint/src/main/java/androidx/appcompat/VanillaCheck.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/appcompat/appcompat-lint/src/main/java/androidx/appcompat/res/ColorStateListAlphaDetector.kt b/appcompat/appcompat-lint/src/main/java/androidx/appcompat/res/ColorStateListAlphaDetector.kt
new file mode 100644
index 0000000..9b7b7c0
--- /dev/null
+++ b/appcompat/appcompat-lint/src/main/java/androidx/appcompat/res/ColorStateListAlphaDetector.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.appcompat.res
+
+import com.android.SdkConstants
+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.LintFix
+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 com.android.tools.lint.detector.api.XmlScanner
+import org.w3c.dom.Element
+
+class ColorStateListAlphaDetector : Detector(), XmlScanner {
+ companion object {
+ internal val NOT_USING_ANDROID_ALPHA: Issue = Issue.create(
+ "UseAndroidAlpha",
+ "`android:alpha` attribute missing on ColorStateList",
+ "ColorStateList uses app:alpha without android:alpha",
+ Category.CORRECTNESS,
+ 1,
+ Severity.ERROR,
+ Implementation(ColorStateListAlphaDetector::class.java, Scope.RESOURCE_FILE_SCOPE)
+ )
+ }
+
+ override fun getApplicableElements(): Collection<String>? = listOf("selector")
+
+ override fun visitElement(context: XmlContext, element: Element) {
+ val items = element.getElementsByTagName("item")
+ for (index in 0 until items.length) {
+ val item = items.item(index) as Element
+ // Only look at items that have android:color
+ if (!item.hasAttributeNS(SdkConstants.ANDROID_URI, "color")) {
+ continue
+ }
+ val hasAppAlphaAttr = item.hasAttributeNS(SdkConstants.AUTO_URI, "alpha")
+ val hasAndroidAlphaAttr = item.hasAttributeNS(SdkConstants.ANDROID_URI, "alpha")
+ if (hasAppAlphaAttr && !hasAndroidAlphaAttr) {
+ context.report(
+ NOT_USING_ANDROID_ALPHA,
+ item,
+ context.getLocation(item),
+ "Must use 'android:alpha' if 'app:alpha' is used.",
+ LintFix.create().set(SdkConstants.ANDROID_URI, "alpha",
+ item.getAttributeNS(SdkConstants.AUTO_URI, "alpha")).build()
+ )
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index e814436..30df614 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/lint-demos/lint-demo-appcompat/OWNERS b/lint-demos/lint-demo-appcompat/OWNERS
new file mode 100644
index 0000000..71598a1
--- /dev/null
+++ b/lint-demos/lint-demo-appcompat/OWNERS
@@ -0,0 +1,3 @@
[email protected]
[email protected]
[email protected]
diff --git a/lint-demos/lint-demo-appcompat/build.gradle b/lint-demos/lint-demo-appcompat/build.gradle
new file mode 100644
index 0000000..9043a79
--- /dev/null
+++ b/lint-demos/lint-demo-appcompat/build.gradle
@@ -0,0 +1,25 @@
+import static androidx.build.dependencies.DependenciesKt.KOTLIN_STDLIB
+
+plugins {
+ id("AndroidXPlugin")
+ id("com.android.application")
+ id("kotlin-android")
+}
+
+dependencies {
+ api 'com.google.android.material:material:1.0.0'
+ implementation(project(":appcompat:appcompat"))
+ implementation(project(":core:core"))
+ api(KOTLIN_STDLIB)
+}
+
+android {
+ defaultConfig {
+ vectorDrawables.useSupportLibrary = true
+ }
+ lintOptions {
+ disable "WrongThread"
+ // TODO: Enable lint after appcompat:1.1.0 release or use lint-baseline.xml instead.
+ abortOnError false
+ }
+}
diff --git a/lint-demos/lint-demo-appcompat/src/main/AndroidManifest.xml b/lint-demos/lint-demo-appcompat/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..5459775
--- /dev/null
+++ b/lint-demos/lint-demo-appcompat/src/main/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.appcompat">
+ <application
+ android:hardwareAccelerated="true"
+ android:icon="@drawable/app_sample_code"
+ android:label="@string/activity_sample_code"
+ android:supportsRtl="true"
+ android:theme="@style/Theme.AppCompat">
+
+ <activity android:name=".AppCompatLintDemo">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/lint-demos/lint-demo-appcompat/src/main/java/com/example/android/appcompat/AppCompatLintDemo.java b/lint-demos/lint-demo-appcompat/src/main/java/com/example/android/appcompat/AppCompatLintDemo.java
new file mode 100644
index 0000000..fae81c3
--- /dev/null
+++ b/lint-demos/lint-demo-appcompat/src/main/java/com/example/android/appcompat/AppCompatLintDemo.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.appcompat;
+
+import android.os.Bundle;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+/**
+ * Dummy activity for the AppCompat Lint demo
+ */
+public class AppCompatLintDemo extends AppCompatActivity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+}
diff --git a/lint-demos/lint-demo-appcompat/src/main/res/color/color_state_list_missing_android_alpha.xml b/lint-demos/lint-demo-appcompat/src/main/res/color/color_state_list_missing_android_alpha.xml
new file mode 100644
index 0000000..a1142a9
--- /dev/null
+++ b/lint-demos/lint-demo-appcompat/src/main/res/color/color_state_list_missing_android_alpha.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+ <item app:alpha="?android:disabledAlpha"
+ android:color="?colorPrimary"
+ android:state_enabled="false"/>
+ <item android:color="?colorPrimary"/>
+</selector>
\ No newline at end of file
diff --git a/lint-demos/lint-demo-appcompat/src/main/res/drawable-hdpi/app_sample_code.png b/lint-demos/lint-demo-appcompat/src/main/res/drawable-hdpi/app_sample_code.png
new file mode 100755
index 0000000..66a1984
--- /dev/null
+++ b/lint-demos/lint-demo-appcompat/src/main/res/drawable-hdpi/app_sample_code.png
Binary files differ
diff --git a/lint-demos/lint-demo-appcompat/src/main/res/values/strings.xml b/lint-demos/lint-demo-appcompat/src/main/res/values/strings.xml
new file mode 100644
index 0000000..fe0e95a
--- /dev/null
+++ b/lint-demos/lint-demo-appcompat/src/main/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <string name="activity_sample_code">Lint Demo AppCompat</string>
+</resources>
diff --git a/settings.gradle b/settings.gradle
index d2ff5f2..7a80011 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -161,6 +161,7 @@
includeProject(":lifecycle:lifecycle-viewmodel", "lifecycle/lifecycle-viewmodel")
includeProject(":lifecycle:lifecycle-viewmodel-ktx", "lifecycle/lifecycle-viewmodel-ktx")
includeProject(":lifecycle:lifecycle-viewmodel-savedstate","lifecycle/lifecycle-viewmodel-savedstate")
+includeProject(":lint-demos:lint-demo-appcompat", "lint-demos/lint-demo-appcompat")
includeProject(":loader:loader", "loader/loader")
includeProject(":loader:loader-ktx", "loader/loader-ktx")
includeProject(":localbroadcastmanager:localbroadcastmanager", "localbroadcastmanager/localbroadcastmanager")