aboutsummaryrefslogtreecommitdiffstats
path: root/lint
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2012-10-14 21:35:42 -0700
committerTor Norbye <tnorbye@google.com>2012-10-15 10:21:17 -0700
commit43849a9c10cf00dc2da2e12e602461c9bd921faa (patch)
treea5bdb22c95a70918eb1e14598efbdabe53d2c26f /lint
parentdb4370b384eccd3cbe1b3f050718b9a87a8d5cf7 (diff)
downloadsdk-43849a9c10cf00dc2da2e12e602461c9bd921faa.zip
sdk-43849a9c10cf00dc2da2e12e602461c9bd921faa.tar.gz
sdk-43849a9c10cf00dc2da2e12e602461c9bd921faa.tar.bz2
Lint detector for missing menu titles
As requested in 38022: Lint should warn when menus don't have a title Change-Id: I34688d7733d98ba9fa8cc10202a5470040962117
Diffstat (limited to 'lint')
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java3
-rw-r--r--lint/libs/lint_checks/src/com/android/tools/lint/checks/TitleDetector.java110
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/TitleDetectorTest.java58
-rw-r--r--lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/menu/titles.xml15
4 files changed, 185 insertions, 1 deletions
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java
index 16a5686..97df003 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java
@@ -55,7 +55,7 @@ public class BuiltinIssueRegistry extends IssueRegistry {
private static final List<Issue> sIssues;
static {
- final int initialCapacity = 117;
+ final int initialCapacity = 118;
List<Issue> issues = new ArrayList<Issue>(initialCapacity);
issues.add(AccessibilityDetector.ISSUE);
@@ -163,6 +163,7 @@ public class BuiltinIssueRegistry extends IssueRegistry {
issues.add(NamespaceDetector.UNUSED);
issues.add(NamespaceDetector.TYPO);
issues.add(AlwaysShowActionDetector.ISSUE);
+ issues.add(TitleDetector.ISSUE);
issues.add(ColorUsageDetector.ISSUE);
issues.add(JavaPerformanceDetector.PAINT_ALLOC);
issues.add(JavaPerformanceDetector.USE_VALUEOF);
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/TitleDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/TitleDetector.java
new file mode 100644
index 0000000..1d1d024
--- /dev/null
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/TitleDetector.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2012 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.android.tools.lint.checks;
+
+import static com.android.SdkConstants.ANDROID_URI;
+import static com.android.SdkConstants.ATTR_TITLE;
+import static com.android.SdkConstants.ATTR_VISIBLE;
+import static com.android.SdkConstants.TAG_ITEM;
+import static com.android.SdkConstants.VALUE_FALSE;
+
+import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
+import com.android.resources.ResourceFolderType;
+import com.android.tools.lint.detector.api.Category;
+import com.android.tools.lint.detector.api.Detector.JavaScanner;
+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.Speed;
+import com.android.tools.lint.detector.api.XmlContext;
+
+import org.w3c.dom.Element;
+
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * Check which makes sure menu items specify a title
+ */
+public class TitleDetector extends ResourceXmlDetector implements JavaScanner {
+ /** The main issue discovered by this detector */
+ public static final Issue ISSUE = Issue.create(
+ "MenuTitle", //$NON-NLS-1$
+ "Ensures that all menu items supply a title",
+
+ "From the action bar documentation:\n" +
+ // u2014: em dash
+ "\"It's important that you always define android:title for each menu item \u2014 " +
+ "even if you don't declare that the title appear with the action item \u2014 for " +
+ "three reasons:\n" +
+ "\n" +
+ "* If there's not enough room in the action bar for the action item, the menu " +
+ "item appears in the overflow menu and only the title appears.\n" +
+ "* Screen readers for sight-impaired users read the menu item's title.\n" +
+ "* If the action item appears with only the icon, a user can long-press the item " +
+ "to reveal a tool-tip that displays the action item's title.\n" +
+ "The android:icon is always optional, but recommended.",
+
+ Category.USABILITY,
+ 5,
+ Severity.WARNING,
+ TitleDetector.class,
+ Scope.RESOURCE_FILE_SCOPE).setMoreInfo(
+ "http://developer.android.com/guide/topics/ui/actionbar.html"); //$NON-NLS-1$
+
+ /** Constructs a new {@link TitleDetector} */
+ public TitleDetector() {
+ }
+
+ @Override
+ public boolean appliesTo(@NonNull ResourceFolderType folderType) {
+ return folderType == ResourceFolderType.MENU;
+ }
+
+ @Override
+ public @NonNull Speed getSpeed() {
+ return Speed.FAST;
+ }
+
+ @Override
+ @Nullable
+ public Collection<String> getApplicableElements() {
+ return Collections.singletonList(TAG_ITEM);
+ }
+
+ @Override
+ public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
+ if (element.hasAttributeNS(ANDROID_URI, ATTR_TITLE)) {
+ return;
+ }
+
+ // TODO: Find out if this is necessary on older versions too.
+ // I swear I saw it mentioned.
+ if (context.getMainProject().getTargetSdk() < 11) {
+ return;
+ }
+
+ if (VALUE_FALSE.equals(element.getAttributeNS(ANDROID_URI, ATTR_VISIBLE))) {
+ return;
+ }
+
+ String message = "Menu items should specify a title";
+ context.report(ISSUE, element, context.getLocation(element), message, null);
+ }
+}
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/TitleDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/TitleDetectorTest.java
new file mode 100644
index 0000000..7259cde
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/TitleDetectorTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 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.android.tools.lint.checks;
+
+import com.android.tools.lint.detector.api.Detector;
+
+@SuppressWarnings("javadoc")
+public class TitleDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new TitleDetector();
+ }
+
+ public void test() throws Exception {
+ assertEquals(
+ "res/menu/titles.xml:3: Warning: Menu items should specify a title [MenuTitle]\n" +
+ " <item android:id=\"@+id/action_bar_progress_spinner\"\n" +
+ " ^\n" +
+ "res/menu/titles.xml:12: Warning: Menu items should specify a title [MenuTitle]\n" +
+ " <item android:id=\"@+id/menu_plus_one\"\n" +
+ " ^\n" +
+ "0 errors, 2 warnings\n",
+
+ lintProject(
+ "apicheck/minsdk14.xml=>AndroidManifest.xml",
+ "res/menu/titles.xml"));
+ }
+
+ public void testOk() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject(
+ "apicheck/minsdk1.xml=>AndroidManifest.xml",
+ "res/menu/titles.xml"));
+ }
+
+ public void testOk2() throws Exception {
+ assertEquals(
+ "No warnings.",
+
+ lintProject("res/menu-land/actions.xml"));
+ }
+}
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/menu/titles.xml b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/menu/titles.xml
new file mode 100644
index 0000000..a1ae5bb
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/res/menu/titles.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:id="@+id/action_bar_progress_spinner"
+ android:showAsAction="always"
+ android:background="@null"
+ android:selectableItemBackground="@null"
+ android:actionLayout="@layout/action_bar_progress_spinner_layout"/>
+ <item android:id="@+id/refresh"
+ android:title="@string/menu_refresh"
+ android:showAsAction="always"
+ android:icon="@drawable/ic_menu_refresh"/>
+ <item android:id="@+id/menu_plus_one"
+ android:showAsAction="always"
+ android:icon="@drawable/ic_menu_plus1"/>
+</menu>