aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Norbye <tnorbye@google.com>2013-01-23 16:52:47 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2013-01-23 16:52:47 +0000
commit021a359c38b70269b1e854ad6c6e4deb61b9cc2f (patch)
tree6e43b081d2360a3d3c0f16fa899cf2ccaa3a9403
parent8f05484bde79afb980283512f85bbbe6cce91200 (diff)
parent57c3a3c8a250f2396909482f34bcc89bf8dd4b6e (diff)
downloadsdk-021a359c38b70269b1e854ad6c6e4deb61b9cc2f.zip
sdk-021a359c38b70269b1e854ad6c6e4deb61b9cc2f.tar.gz
sdk-021a359c38b70269b1e854ad6c6e4deb61b9cc2f.tar.bz2
Merge "Add new lint Checks for manifest typos."
-rw-r--r--common/src/main/java/com/android/SdkConstants.java1
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/ManifestTypoDetectorTest.java184
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_not_found.xml28
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_feature.xml28
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_feature2.xml28
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_library.xml28
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_library2.xml28
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_permission.xml28
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_permission2.xml28
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_sdk.xml28
-rw-r--r--lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_sdk2.xml28
-rw-r--r--lint/libs/lint_checks/src/main/java/com/android/tools/lint/checks/BuiltinIssueRegistry.java3
-rw-r--r--lint/libs/lint_checks/src/main/java/com/android/tools/lint/checks/ManifestTypoDetector.java136
13 files changed, 575 insertions, 1 deletions
diff --git a/common/src/main/java/com/android/SdkConstants.java b/common/src/main/java/com/android/SdkConstants.java
index a0fdc39..5ce9645 100644
--- a/common/src/main/java/com/android/SdkConstants.java
+++ b/common/src/main/java/com/android/SdkConstants.java
@@ -594,6 +594,7 @@ public final class SdkConstants {
// Tags: Manifest
public static final String TAG_SERVICE = "service"; //$NON-NLS-1$
public static final String TAG_PERMISSION = "permission"; //$NON-NLS-1$
+ public static final String TAG_USES_FEATURE = "uses-feature"; //$NON-NLS-1$
public static final String TAG_USES_PERMISSION = "uses-permission";//$NON-NLS-1$
public static final String TAG_USES_LIBRARY = "uses-library"; //$NON-NLS-1$
public static final String TAG_APPLICATION = "application"; //$NON-NLS-1$
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/ManifestTypoDetectorTest.java b/lint/cli/src/test/java/com/android/tools/lint/checks/ManifestTypoDetectorTest.java
new file mode 100644
index 0000000..f0ce60d
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/ManifestTypoDetectorTest.java
@@ -0,0 +1,184 @@
+/*
+ * 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.android.tools.lint.checks;
+
+import com.android.annotations.NonNull;
+import com.android.tools.lint.client.api.LintClient;
+import com.android.tools.lint.detector.api.Detector;
+import com.android.tools.lint.detector.api.Issue;
+import com.android.tools.lint.detector.api.Project;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+@SuppressWarnings("javadoc")
+public class ManifestTypoDetectorTest extends AbstractCheckTest {
+ @Override
+ protected Detector getDetector() {
+ return new ManifestTypoDetector();
+ }
+
+ private Set<Issue> mEnabled = new HashSet<Issue>();
+
+ @Override
+ protected TestConfiguration getConfiguration(LintClient client, Project project) {
+ return new TestConfiguration(client, project, null) {
+ @Override
+ public boolean isEnabled(@NonNull Issue issue) {
+ return super.isEnabled(issue) && mEnabled.contains(issue);
+ }
+ };
+ }
+
+ public void testOk() throws Exception {
+ mEnabled = Collections.singleton(ManifestTypoDetector.ISSUE);
+ assertEquals(
+ "No warnings.",
+ lintProject(
+ "typo_not_found.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testTypoUsesSdk() throws Exception {
+ mEnabled = Collections.singleton(ManifestTypoDetector.ISSUE);
+ assertEquals(
+ "AndroidManifest.xml:7: " +
+ "Warning: <use-sdk> looks like a typo; did you mean <uses-sdk> ? [ManifestTypos]\n" +
+ " <use-sdk android:minSdkVersion=\"14\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject(
+ "typo_uses_sdk.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testTypoUsesSdk2() throws Exception {
+ mEnabled = Collections.singleton(ManifestTypoDetector.ISSUE);
+ assertEquals(
+ "AndroidManifest.xml:7: " +
+ "Warning: <user-sdk> looks like a typo; did you mean <uses-sdk> ? [ManifestTypos]\n" +
+ " <user-sdk android:minSdkVersion=\"14\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject(
+ "typo_uses_sdk2.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testTypoUsesPermission() throws Exception {
+ mEnabled = Collections.singleton(ManifestTypoDetector.ISSUE);
+ assertEquals(
+ "AndroidManifest.xml:9: " +
+ "Warning: <use-permission> looks like a typo; " +
+ "did you mean <uses-permission> ? [ManifestTypos]\n" +
+ " <use-permission android:name=\"com.example.helloworld.permission\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject(
+ "typo_uses_permission.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testTypoUsesPermission2() throws Exception {
+ mEnabled = Collections.singleton(ManifestTypoDetector.ISSUE);
+ assertEquals(
+ "AndroidManifest.xml:9: " +
+ "Warning: <user-permission> looks like a typo; " +
+ "did you mean <uses-permission> ? [ManifestTypos]\n" +
+ " <user-permission android:name=\"com.example.helloworld.permission\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject(
+ "typo_uses_permission2.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testTypoUsesFeature() throws Exception {
+ mEnabled = Collections.singleton(ManifestTypoDetector.ISSUE);
+ assertEquals(
+ "AndroidManifest.xml:11: " +
+ "Warning: <use-feature> looks like a typo; " +
+ "did you mean <uses-feature> ? [ManifestTypos]\n" +
+ " <use-feature android:name=\"android.hardware.wifi\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject(
+ "typo_uses_feature.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testTypoUsesFeature2() throws Exception {
+ mEnabled = Collections.singleton(ManifestTypoDetector.ISSUE);
+ assertEquals(
+ "AndroidManifest.xml:11: " +
+ "Warning: <user-feature> looks like a typo; " +
+ "did you mean <uses-feature> ? [ManifestTypos]\n" +
+ " <user-feature android:name=\"android.hardware.wifi\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject(
+ "typo_uses_feature2.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testTypoUsesLibrary() throws Exception {
+ mEnabled = Collections.singleton(ManifestTypoDetector.ISSUE);
+ assertEquals(
+ "AndroidManifest.xml:16: " +
+ "Warning: <use-library> looks like a typo; " +
+ "did you mean <uses-library> ? [ManifestTypos]\n" +
+ " <use-library android:name=\"com.example.helloworld\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject(
+ "typo_uses_library.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+
+ public void testTypoUsesLibrary2() throws Exception {
+ mEnabled = Collections.singleton(ManifestTypoDetector.ISSUE);
+ assertEquals(
+ "AndroidManifest.xml:16: " +
+ "Warning: <user-library> looks like a typo; " +
+ "did you mean <uses-library> ? [ManifestTypos]\n" +
+ " <user-library android:name=\"com.example.helloworld\" />\n" +
+ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n" +
+ "0 errors, 1 warnings\n" +
+ "",
+
+ lintProject(
+ "typo_uses_library2.xml=>AndroidManifest.xml",
+ "res/values/strings.xml"));
+ }
+}
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_not_found.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_not_found.xml
new file mode 100644
index 0000000..9cd3640
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_not_found.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <uses-permission android:name="com.example.helloworld.permission" />
+
+ <uses-feature android:name="android.hardware.wifi" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <uses-library android:name="com.example.helloworld" />
+ <activity
+ android:label="@string/app_name"
+ android:name=".Foo2Activity" >
+ <intent-filter >
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_feature.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_feature.xml
new file mode 100644
index 0000000..cff7f2e
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_feature.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <uses-permission android:name="com.example.helloworld.permission" />
+
+ <use-feature android:name="android.hardware.wifi" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <uses-library android:name="com.example.helloworld" />
+ <activity
+ android:label="@string/app_name"
+ android:name=".Foo2Activity" >
+ <intent-filter >
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_feature2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_feature2.xml
new file mode 100644
index 0000000..d4d8f6e
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_feature2.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <uses-permission android:name="com.example.helloworld.permission" />
+
+ <user-feature android:name="android.hardware.wifi" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <uses-library android:name="com.example.helloworld" />
+ <activity
+ android:label="@string/app_name"
+ android:name=".Foo2Activity" >
+ <intent-filter >
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_library.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_library.xml
new file mode 100644
index 0000000..5273642
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_library.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <uses-permission android:name="com.example.helloworld.permission" />
+
+ <uses-feature android:name="android.hardware.wifi" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <use-library android:name="com.example.helloworld" />
+ <activity
+ android:label="@string/app_name"
+ android:name=".Foo2Activity" >
+ <intent-filter >
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_library2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_library2.xml
new file mode 100644
index 0000000..966caf4
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_library2.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <uses-permission android:name="com.example.helloworld.permission" />
+
+ <uses-feature android:name="android.hardware.wifi" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <user-library android:name="com.example.helloworld" />
+ <activity
+ android:label="@string/app_name"
+ android:name=".Foo2Activity" >
+ <intent-filter >
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_permission.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_permission.xml
new file mode 100644
index 0000000..18a31ae
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_permission.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <use-permission android:name="com.example.helloworld.permission" />
+
+ <uses-feature android:name="android.hardware.wifi" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <uses-library android:name="com.example.helloworld" />
+ <activity
+ android:label="@string/app_name"
+ android:name=".Foo2Activity" >
+ <intent-filter >
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_permission2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_permission2.xml
new file mode 100644
index 0000000..2f070c5
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_permission2.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="14" />
+
+ <user-permission android:name="com.example.helloworld.permission" />
+
+ <uses-feature android:name="android.hardware.wifi" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <uses-library android:name="com.example.helloworld" />
+ <activity
+ android:label="@string/app_name"
+ android:name=".Foo2Activity" >
+ <intent-filter >
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_sdk.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_sdk.xml
new file mode 100644
index 0000000..c086515
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_sdk.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <use-sdk android:minSdkVersion="14" />
+
+ <uses-permission android:name="com.example.helloworld.permission" />
+
+ <uses-feature android:name="android.hardware.wifi" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <uses-library android:name="com.example.helloworld" />
+ <activity
+ android:label="@string/app_name"
+ android:name=".Foo2Activity" >
+ <intent-filter >
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_sdk2.xml b/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_sdk2.xml
new file mode 100644
index 0000000..148a3fc
--- /dev/null
+++ b/lint/cli/src/test/java/com/android/tools/lint/checks/data/typo_uses_sdk2.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="foo.bar2"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <user-sdk android:minSdkVersion="14" />
+
+ <uses-permission android:name="com.example.helloworld.permission" />
+
+ <uses-feature android:name="android.hardware.wifi" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <uses-library android:name="com.example.helloworld" />
+ <activity
+ android:label="@string/app_name"
+ android:name=".Foo2Activity" >
+ <intent-filter >
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/lint/libs/lint_checks/src/main/java/com/android/tools/lint/checks/BuiltinIssueRegistry.java b/lint/libs/lint_checks/src/main/java/com/android/tools/lint/checks/BuiltinIssueRegistry.java
index 90ebfd8..1ebb701 100644
--- a/lint/libs/lint_checks/src/main/java/com/android/tools/lint/checks/BuiltinIssueRegistry.java
+++ b/lint/libs/lint_checks/src/main/java/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 = 140;
+ final int initialCapacity = 141;
List<Issue> issues = new ArrayList<Issue>(initialCapacity);
issues.add(AccessibilityDetector.ISSUE);
@@ -137,6 +137,7 @@ public class BuiltinIssueRegistry extends IssueRegistry {
issues.add(ManifestOrderDetector.UNIQUE_PERMISSION);
issues.add(ManifestOrderDetector.SET_VERSION);
issues.add(ManifestOrderDetector.ILLEGAL_REFERENCE);
+ issues.add(ManifestTypoDetector.ISSUE);
issues.add(SecurityDetector.EXPORTED_PROVIDER);
issues.add(SecurityDetector.EXPORTED_SERVICE);
issues.add(SecurityDetector.EXPORTED_RECEIVER);
diff --git a/lint/libs/lint_checks/src/main/java/com/android/tools/lint/checks/ManifestTypoDetector.java b/lint/libs/lint_checks/src/main/java/com/android/tools/lint/checks/ManifestTypoDetector.java
new file mode 100644
index 0000000..cc85be6
--- /dev/null
+++ b/lint/libs/lint_checks/src/main/java/com/android/tools/lint/checks/ManifestTypoDetector.java
@@ -0,0 +1,136 @@
+/*
+ * 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.android.tools.lint.checks;
+
+import static com.android.SdkConstants.ANDROID_MANIFEST_XML;
+import static com.android.SdkConstants.TAG_USES_FEATURE;
+import static com.android.SdkConstants.TAG_USES_LIBRARY;
+import static com.android.SdkConstants.TAG_USES_PERMISSION;
+import static com.android.SdkConstants.TAG_USES_SDK;
+
+import com.android.SdkConstants;
+import com.android.annotations.NonNull;
+import com.android.tools.lint.detector.api.Category;
+import com.android.tools.lint.detector.api.Context;
+import com.android.tools.lint.detector.api.Detector;
+import com.android.tools.lint.detector.api.Issue;
+import com.android.tools.lint.detector.api.Location;
+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 com.google.common.collect.Maps;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+/**
+ * Checks for typos in AndroidManifest files.
+ */
+public class ManifestTypoDetector extends Detector implements Detector.XmlScanner {
+
+ private static final String REPORT_FORMAT
+ = "<%1$s> looks like a typo; did you mean <%2$s> ?";
+
+ /* The match pattern for <uses-sdk> */
+ private static final Pattern PATTERN_USES_SDK
+ = Pattern.compile("^use.*sdk"); //$NON-NLS-1$
+
+ /* The match pattern for <uses-permission> */
+ private static final Pattern PATTERN_USES_PERMISSION
+ = Pattern.compile("^use.*permission"); //$NON-NLS-1$
+
+ /* The match pattern for <uses-feature> */
+ private static final Pattern PATTERN_USES_FEATURE
+ = Pattern.compile("^use.*feature"); //$NON-NLS-1$
+
+ /* The match pattern for <uses-library> */
+ private static final Pattern PATTERN_USES_LIBRARY
+ = Pattern.compile("^use.*library"); //$NON-NLS-1$
+
+ /** The main issue discovered by this detector */
+ public static final Issue ISSUE = Issue.create(
+ "ManifestTypo", //$NON-NLS-1$
+ "Checks for manifest typos",
+
+ "This check looks through the manifest, and if it finds any tags " +
+ "that look like likely misspellings, they are flagged.",
+ Category.CORRECTNESS,
+ 5,
+ Severity.WARNING,
+ ManifestTypoDetector.class,
+ Scope.MANIFEST_SCOPE);
+
+ /** Constructs a new {@link ManifestTypoDetector} check */
+ public ManifestTypoDetector() {
+ }
+
+ @NonNull
+ @Override
+ public Speed getSpeed() {
+ return Speed.FAST;
+ }
+
+ @Override
+ public boolean appliesTo(@NonNull Context context, @NonNull File file) {
+ return file.getName().equals(ANDROID_MANIFEST_XML);
+ }
+
+ @Override
+ public Collection<String> getApplicableElements() {
+ return XmlScanner.ALL;
+ }
+
+ @Override
+ public void visitElement(@NonNull XmlContext context, @NonNull Element element) {
+ String tag = element.getTagName();
+
+ if (!tag.startsWith("use")) { //$NON-NLS-1$
+ return;
+ }
+
+ if (PATTERN_USES_SDK.matcher(tag).find() && !TAG_USES_SDK.equals(tag)) {
+ context.report(ISSUE, context.getLocation(element),
+ String.format(REPORT_FORMAT, tag, TAG_USES_SDK), null);
+ }
+
+ if (PATTERN_USES_PERMISSION.matcher(tag).find() && !TAG_USES_PERMISSION.equals(tag)) {
+ context.report(ISSUE, context.getLocation(element),
+ String.format(REPORT_FORMAT, tag, TAG_USES_PERMISSION), null);
+ }
+
+ if (PATTERN_USES_FEATURE.matcher(tag).find() && !TAG_USES_FEATURE.equals(tag)) {
+ context.report(ISSUE, context.getLocation(element),
+ String.format(REPORT_FORMAT, tag, TAG_USES_FEATURE), null);
+ }
+
+ if (PATTERN_USES_LIBRARY.matcher(tag).find() && !TAG_USES_LIBRARY.equals(tag)) {
+ context.report(ISSUE, context.getLocation(element),
+ String.format(REPORT_FORMAT, tag, TAG_USES_LIBRARY), null);
+ }
+ }
+}